R流水线功能

时间:2012-11-13 00:46:11

标签: r pipeline

有没有办法在R中编写流水线函数,其中一个函数的结果立即传递到下一个函数?我来自F#并且非常欣赏这种能力,但还没有找到如何在R中做到这一点。它应该很简单,但我找不到如何。在F#中它看起来像这样:

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

在这种情况下,输入将被平方,然后添加5,然后转换为字符串。我希望能够在R中做类似的事情,但不知道如何做。我已经搜索了如何做这样的事情,但没有遇到任何问题。我想要导入数据,因为我通常必须导入它然后过滤。现在我通过多个步骤完成这项工作,并且非常希望能够像管道中的F#那样做。

5 个答案:

答案 0 :(得分:8)

这是使用Reduce的函数式编程方法。它实际上是?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"

甚至更简单地使用functional包和Compose

这很好,因为它会为你创建功能

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

我注意到我不会在惯用R ish(如果这甚至是一个短语)中考虑这些方法中的任何一个

答案 1 :(得分:7)

我们可以使用函数包中的Compose来创建我们自己的二进制运算符,它可以执行类似于你想要的操作

# 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) }

我想我们可以在技术上做到这一点而不需要功能包 - 但是使用Compose来完成这项任务感觉非常正确。

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

答案 2 :(得分:5)

我认为你可能只想写一个函数来完成你想要的步骤。

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

然后拨打complexFunction(x)


编辑以显示 R 在内部执行的操作(@mnel) - R解析和评估as.character(x^2 + 5)的方式可以执行您想要的操作

您可以使用codetools调查R查看价值如何传递给彼此的内容

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*`)

或者您可以获取Lisp样式表示以查看它是如何解析的(并且结果已通过)

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

答案 3 :(得分:1)

自从提出这个问题以来,magrittr管道在R中变得非常流行。所以你的例子是:

library (magrittr)

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

请注意,反引号符号是因为我实际上使用了R的内置函数,我需要特别引用它们以这种方式使用它们。更多通常命名的函数(如exp或者如果我创建了辅助函数add)不需要反引号,看起来更像你的例子。

另请注意,%>%会自动将传入值作为第一个参数传递给下一个函数,但您可以更改此值。另请注意,R函数返回计算的最后一个值,因此我不需要return或指定计算以便返回它。

这很像其他答案定义的漂亮的特殊运算符,但它使用了一种在R中广泛使用的特殊函数。

答案 4 :(得分:0)

这适用于F#中的R非常相似:

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