有没有办法在R中编写流水线函数,其中一个函数的结果立即传递到下一个函数?我来自F#并且非常欣赏这种能力,但还没有找到如何在R中做到这一点。它应该很简单,但我找不到如何。在F#中它看起来像这样:
let complexFunction x =
x |> square
|> add 5
|> toString
在这种情况下,输入将被平方,然后添加5,然后转换为字符串。我希望能够在R中做类似的事情,但不知道如何做。我已经搜索了如何做这样的事情,但没有遇到任何问题。我想要导入数据,因为我通常必须导入它然后过滤。现在我通过多个步骤完成这项工作,并且非常希望能够像管道中的F#那样做。
答案 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)
}
}