Funktionen auf höherer Ebene in R - Gibt es einen offiziellen Komponierungsbetreiber oder eine Curry -Funktion?

StackOverflow https://stackoverflow.com/questions/2228544

Frage

Ich kann einen Kompose -Operator in R erstellen:

 `%c%` = function(x,y)function(...)x(y(...)) 

So verwendet werden:

 > numericNull = is.null %c% numeric
 > numericNull(myVec)
 [2] TRUE FALSE

Aber ich würde gerne wissen, ob es offizielle Funktionen gibt, die so etwas und andere Operationen wie Currying in R durchführen, vor allem die Anzahl der Klammern, Funktionsschlüsselwörter usw. in meinem Code reduzieren.

Meine Curry -Funktion:

> curry=function(...){
    z1=z0=substitute(...);z1[1]=call("list");
    function(...){do.call(as.character(z0[[1]]),
                          as.list(c(eval(z1),list(...))))}}
> p = curry(paste(collapse=""))
> p(letters[1:10])
[1] "abcdefghij"

Dies ist besonders schön für z. B. Aggregat:

> df = data.frame(l=sample(1:3,10,rep=TRUE), t=letters[1:10])
> aggregate(df$t,df["l"],curry(paste(collapse="")) %c% toupper)
  l    x
1 1  ADG
2 2  BCH
3 3 EFIJ

Was ich viel eleganter und bearbeitbarer finde als:

> aggregate(df$t, df["l"], function(x)paste(collapse="",toupper(x)))
  l    x
1 1  ADG
2 2  BCH
3 3 EFIJ

Grundsätzlich möchte ich es wissen - wurde dies bereits für R getan?

War es hilfreich?

Lösung

Der Standardplatz für die funktionale Programmierung in R ist jetzt die functional Bibliothek.

Aus der Bibliothek:

Funktional: Curry, Komponieren und andere Funktionen höherer Ordnung

Beispiel:

   library(functional)
   newfunc <- Curry(oldfunc,x=5)

Kran:https://cran.r-project.org/web/packages/functional/index.html

PS: Diese Bibliothek ersetzt die ROxigen Bibliothek.

Andere Tipps

Beide Funktionen existieren tatsächlich in das roxygen Paket (Siehe den Quellcode hier) von Peter Dänitätsberg (basiert ursprünglich auf Byron Ellis 'Lösung auf R-Help):

Curry <- function(FUN,...) {
  .orig = list(...);
  function(...) do.call(FUN,c(.orig,list(...)))
}

Compose <- function(...) {
  fs <- list(...)
  function(...) Reduce(function(x, f) f(x),
                       fs,
                       ...)
}

Beachten Sie die Verwendung des Reduce Funktion, die sehr hilfreich sein kann, wenn Sie versuchen, funktionale Programmierung in R zu machen, siehe. Reduzieren Sie für weitere Details (was auch andere Funktionen wie z. Map und Filter).

Und Ihr Beispiel für Curry (etwas anders in dieser Verwendung):

> library(roxygen)
> p <- Curry(paste, collapse="")
> p(letters[1:10])
[1] "abcdefghij"

Hier ist ein Beispiel, um den Nutzen von zu zeigen Compose (Anwenden von drei verschiedenen Funktionen auf Buchstaben):

> Compose(function(x) x[length(x):1], Curry(paste, collapse=""), toupper)(letters)
[1] "ZYXWVUTSRQPONMLKJIHGFEDCBA"

Und Ihr letztes Beispiel würde so funktionieren:

> aggregate(df[,"t"], df["l"], Compose(Curry(paste, collapse=""), toupper))
  l    x
1 1  ABG
2 2 DEFH
3 3  CIJ

Zuletzt hier ist eine Möglichkeit, dasselbe mitzumachen plyr (könnte auch leicht mit erledigt werden by oder aggregate Wie bereits gezeigt):

> library(plyr)
> ddply(df, .(l), function(df) paste(toupper(df[,"t"]), collapse=""))
  l   V1
1 1  ABG
2 2 DEFH
3 3  CIJ

Es gibt eine Funktion namens Curry in der Roxygen Paket.
VIV VIV dieses Gespräch Auf dem R -Mail -Archiv.

Ein komplexerer Ansatz ist erforderlich, wenn Sie möchten, dass die "Namen" der Variablen genau durchlaufen.

Zum Beispiel, wenn Sie dies tun plot(rnorm(1000),rnorm(1000)) Dann erhalten Sie schöne Etiketten auf Ihren X- und Y-Achsen. Ein weiteres Beispiel dafür ist data.frame

> data.frame( rnorm(5), rnorm(5), first=rpois(5,1), second=rbinom(5,1,0.5) )
    rnorm.5. rnorm.5..1 first second
1  0.1964190 -0.2949770     0      0
2  0.4750665  0.8849750     1      0
3 -0.7829424  0.4174636     2      0
4  1.6551403  1.3547863     0      1
5  1.4044107 -0.4216046     0      0

Nicht, dass der Daten.Frame den Spalten nützliche Namen zugewiesen hat.

Einige Implementierungen von Curry tun dies möglicherweise nicht ordnungsgemäß, was zu unlesbaren Spaltennamen und Handlungsbezeichnungen führt. Stattdessen benutze ich jetzt so etwas:

Curry <- function(FUN, ...) {
    .orig = match.call()
    .orig[[1]] <- NULL # Remove first item, which matches Curry
    .orig[[1]] <- NULL # Remove another item, which matches FUN
    function(...) {
        .inner = match.call()
        .inner[[1]] <- NULL # Remove first item, which matches Curry
        do.call(FUN, c(.orig, .inner), envir=parent.frame())
    }
}

Das ist ziemlich komplex, aber ich denke, es ist richtig. match.call Ich werde alle Argumente fangen und sich voll und ganz daran erinnern, welche Ausdrücke die Argumente definiert haben (dies ist für schöne Beschriftungen erforderlich). Das Problem ist, dass es zu viele Argumentationen fängt - nicht nur das ... aber auch die FUN. Es erinnert sich auch an den Namen der Funktion, die aufgerufen wird ((Curry).

Daher möchten wir diese ersten beiden Einträge in löschen .orig so dass .orig entspricht wirklich dem ... Argumente. Deshalb tun wir .orig[[1]]<-NULL Zweimal - jedes Mal löscht und verschiebt alles andere nach links.

Dies vervollständigt die Definition und wir können jetzt Folgendes tun, um zu bekommen exakt das gleiche wie oben

Curry(data.frame, rnorm(5), rnorm(5) )( first=rpois(5,1) , second=rbinom(5,1,0.5) )

Eine letzte Notiz zu envir=parent.frame(). Ich habe dies verwendet, um sicherzustellen, dass es kein Problem gibt, wenn Sie externe Variablen namens '.inner' oder '.Orig' haben. Jetzt werden alle Variablen an der Stelle bewertet, an der das Curry aufgerufen wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top