2012-11-13 9 views
14

Gibt es eine Möglichkeit, Pipeline-Funktionen in R zu schreiben, wo das Ergebnis einer Funktion sofort in die nächste übergeht? Ich komme aus F # und schätze diese Fähigkeit wirklich, habe aber nicht herausgefunden, wie man es in R macht. Es sollte einfach sein, aber ich kann nicht finden, wie. In F # wäre es etwa so aussehen:R Pipelining-Funktionen

let complexFunction x = 
    x |> square 
    |> add 5 
    |> toString 

In diesem Fall ist der Eingang zum Quadrat würde, dann haben 5 bis hinzugefügt und dann in einen String umgewandelt. Ich möchte etwas Ähnliches in R machen können, weiß aber nicht wie. Ich habe nach etwas gesucht, aber noch nichts gefunden. Ich möchte dies für den Import von Daten, weil ich es normalerweise importieren und dann filtern muss. Im Moment mache ich das in mehreren Schritten und würde wirklich gerne etwas so machen können wie in F # mit Pipelines.

+1

Ich bin nicht ganz klar in was Sie fragen: 'complexFunction <- function (x) {x <- x^2; x <- x + 5; x <- as.zeichen (x); return (x)} ' –

+1

Mögliche Duplikate: http://StackOverflow.com/Questions/7290947/Data-Manipulation-in-Rin-in-Linq-Style – Owen

+0

mögliche Duplikate von [wie zu implementieren F # 's Forward Pipe Operator in R? ] (http://stackoverflow.com/questions/8896820/how-to-implement-fs-forward-pipe-operator-in-r) –

Antwort

7

Wir Compose aus dem Funktionspaket nutzen können unsere eigenen Binäroperators zu erstellen, die etwas ähnliches tut, was Sie wollen

# Define our helper functions 
square <- function(x){x^2} 
add5 <- function(x){x + 5} 

# functional contains Compose 
library(functional) 

# Define our binary operator 
"%|>%" <- Compose 

# Create our complexFunction by 'piping' our functions 
complexFunction <- square %|>% add5 %|>% as.character 
complexFunction(1:5) 
#[1] "6" "9" "14" "21" "30" 


# previously had this until flodel pointed out 
# that the above was sufficient 
#"%|>%" <- function(fun1, fun2){ Compose(fun1, fun2) } 

Ich denke, wir konnten technisch Tun Sie dies, ohne das Funktionspaket zu benötigen - aber es fühlt sich so richtig an, Compose für diese Aufgabe zu verwenden.

"%|>%" <- function(fun1, fun2){ 
    function(x){fun2(fun1(x))} 
} 
complexFunction <- square %|>% add5 %|>% as.character 
complexFunction(1:5) 
#[1] "6" "9" "14" "21" "30" 
+0

Können wir die zwei '%%' Symbole in '% |> loswerden % '? Sie sehen hässlich und umständlich aus. Oder gibt es irgendeine Besonderheit für %% in R? Ich kann keine Erklärung in der Dokumentation finden. – Nick

+0

Sie sind erforderlich. Ich weiß nicht, wo es in der Dokumentation erwähnt wird, wie man diese Dinge definiert, aber es ist irgendwo da. Benutzerdefinierte binäre Infixoperatoren haben immer die Form '% something %' – Dason

5

Ich denke, dass Sie vielleicht nur eine Funktion schreiben möchten, um die Schritte zu tun, die Sie wünschen.

complexFunction <- function(x) { 
    as.character(x^2 + 5) 
} 

Dann rufen Sie einfach complexFunction(x).


bearbeiten zu zeigen, was R intern (@mnel) tut - Die Art und Weise R die analysiert und bewertet as.character(x^2 + 5) tut, was Sie

Sie wollen codetoolsR was zu untersuchen, verwenden können, um zu sehen, wie die Werte werden an einander

geben
flattenAssignment(quote(as.character(x^2+5))) 
[[1]] 
[[1]][[1]] 
x 

[[1]][[2]] 
`*tmp*`^2 

[[1]][[3]] 
`*tmp*` + 5 


[[2]] 
[[2]][[1]] 
`as.character<-`(`*tmp*`, value = `*tmpv*`) 

[[2]][[2]] 
`+<-`(`*tmp*`, 5, value = `*tmpv*`) 

[[2]][[3]] 
`^<-`(x, 2, value = `*tmpv*`) 

Oder Sie können die Lisp Stil Darstellung zu sehen bekommen, wie es (und die Ergebnisse p analysiert wird assed)

showTree(quote(as.character(x^2+5))) 
(as.character (+ (^ x 2) 5)) 
8

Hier ist eine funktionale Programmierung Ansatz Reduce verwenden. Es ist in der Tat ein Beispiel aus ?Reduce

square <- function(x) x^2 
add_5 <- function(x) x+5 
x <- 1:5 
## Iterative function application: 
Funcall <- function(f, ...) f(...) 

Reduce(Funcall, list(as.character, add_5, square,x), right = TRUE) 
## [1] "6" "9" "14" "21" "30" 

Oder noch einfacher mit dem functional Paket und Compose

Das ist schön, da es die Funktion für Sie

library(functional) 
do_stuff <- Compose(square,add_5,as.character) 
do_stuff(1:5) 
## [1] "6" "9" "14" "21" "30" 

erstellen

Ich bemerke, dass ich keine dieser App betrachten würde idiomatisch R ish Rotaugen (wenn das überhaupt ein Begriff ist)

0

Das für R ziemlich ähnlich in F # funktioniert:

"%|>%" <- function(x, fun){ 
    if(is.function(x)) { 
     function(...) fun(x(...)) 
    } else { 
     fun(x) 
    } 
} 
0

Da diese Frage gestellt wurde, das magrittr Rohr enorm populär in R. würde So hat sich Ihr Beispiel sein:

library (magrittr) 

fx <- function (x) { 
    x %>% 
    `^` (2) %>% 
    `+` (5) %>% 
    as.character() 
    } 

Beachten Sie, dass die Backquote-Notation ist, weil ich buchstäblich die eingebauten Funktionen von R verwende und ich muss sie speziell zitieren, um sie auf diese Weise zu verwenden. Weitere normal benannte Funktionen (wie exp oder wenn ich eine Hilfsfunktion add erstellt hätte) würden keine Backquotes benötigen und würden eher wie Ihr Beispiel aussehen.

Beachten Sie auch, dass %>% den eingehenden Wert automatisch als erstes Argument an die nächste Funktion übergibt, obwohl Sie dies ändern können. Beachten Sie auch, dass eine R-Funktion den letzten berechneten Wert zurückgibt, so dass ich weder return noch die Berechnung zuordnen muss, um sie zurückzugeben.

Dies ist ähnlich wie die netten Sonderoperatoren, die von anderen Antworten definiert werden, aber es verwendet eine bestimmte Funktion, die jetzt in R weit verbreitet ist.