是否可以在R?
中链接函数示例数据:
m <- matrix(c(1:10, 11:20), nrow = 10, ncol = 2)
例如,我想替换以下语句:
step1 <- mean(m)
step2 <- sum(step1)
res <- step2
或者,
res <- sum(mean(m))
有这样的事情:
res <- m@mean()@sum()
在某些情况下,这会大大澄清我的代码。
EDIT1 这是一个虚拟的例子。我随机选择了'sum'和'mean'。
Ben使用%@%给出了第一个答案,但它阻止在函数中使用额外的参数:
m %@% function1(arg1, arg2) %@% function2(arg1, arg2)
我该如何解决这个问题?
EDIT2 添加示例
require(xts)
require(PerformanceAnalytics)
xts.ts <- xts(rnorm(231),as.Date(13514:13744,origin="1970-01-01"))
plot(na.omit(lag( rollapply(xts.ts, width=rolling.per-1, FUN= function(x){sqrt(var(x))*sqrt(252)}), k=1)), main = "Dummy Example")
此示例似乎与Charles解决方案一起正常工作:
`%@%` <- function(x, f) eval.parent(as.call(append(as.list(substitute(f)), list(x), 1)))
xts.ts %@% rollapply( width = rolling.per-1, FUN= function(x) x%@%var%@%sqrt * sqrt(252) ) %@% lag( k=1) %@% na.omit %@% plot(main = "Dummy Example")
对我的案子不太重要,但是提到的是,以下的陈述在Charles的解决方案中失败了:
xts.ts %@% names <- 'ts name'
答案 0 :(得分:12)
尝试功能包:
library(functional)
squared <- function(x)x*x
Compose(sum, squared)(m)
## [1] 44100
squared(sum(m))
## [1] 44100
编辑:
关于有关参数的另一个回复的评论中的问题,这里是一个用参数组成的例子。 Curry
也来自功能包:
addn <- function(n, x) x + n
Compose(Curry(addn, 1), squared)(10)
## [1] 121
squared(addn(1, 10))
## [1] 121
编辑2:
关于调试的问题,debug
如果函数是咖喱的,则有效。如果它还没有咖喱,那么将其包裹在Curry
:
# this works since addn is curried
debug(addn)
Compose(Curry(addn, 1), squared)(10)
# to debug squared put it in a Curry -- so this works:
debug(squared)
Compose(Curry(addn, 1), Curry(squared))(10)
答案 1 :(得分:9)
排序,但我认为这不是惯用的,也许是脆弱的/不是个好主意。 (我认为,这可以通过@ RichieCotton上面的评论暗示。)
来自http://cran.r-project.org/doc/manuals/R-lang.html:
10.3.4特殊操作员
R允许用户定义的中缀运算符。它们具有由'%'字符分隔的字符串形式。字符串可以 包含除'%'以外的任何可打印字符。逃逸序列 字符串不适用于此。
请注意,以下运算符是预定义的
%% %*% %/% %in% %o% %x%
"%@%" <- function(x,f) {
f(x)
}
sqr <- function(x) x^2
x <- 1:4
x %@% mean ## 2.5
x %@% mean %@% sqr ## 6.25
x %@% (mean %@% sqr) ## fails
鉴于上面定义的m
- 也许你想到的是什么?
m %@% colMeans %@% sum ## 21
注意:
mean(x)
总是返回一个标量(即长度为1的向量),所以sum(mean(x))
总是与mean(x)
相同%
包围,因此您不能拥有像单个符号那样紧凑的内容(并且已经采用%%
)。 编辑:问题现在询问如何合并其他参数。我不认为建议的语法(x %@% fun1(arg1) %@% fun2(arg2)
)可以在没有一些严重魔法的情况下起作用。这是我目前最接近的 - 创建一个包装函数,创建原始函数的修改版本。
F <- function(f,...) {
function(x) {
f(x,...)
}
}
测试:
pow <- function(x,b=2) { x^b }
sqr <- function(x) x^2
x <- 1:4
x %@% F(mean,na.rm=TRUE) ## 2.5
x %@% F(mean,na.rm=TRUE) %@% F(pow,3) ## 16.25
(请注意,我在这里使用F
作为函数,在某些情况下可能会有点冒险,因为它会覆盖F==FALSE
快捷方式)
答案 2 :(得分:4)
与Ben的答案类似,但允许参数:
`%@%` <- function(x, f) eval.parent(as.call(append(as.list(substitute(f)), list(x), 1)))
x %@% mean %@% sqr # => 6.25
c(1, 2, NA, 3, 4) %@% mean(na.rm=T) %@% sqr # => 6.25
m %@% colMeans() %@% sum() # => 21
答案 3 :(得分:4)
我会使用magrittr
包。它有一个&#34;管道&#34;获取一个函数的结果并将其作为参数传递给下一个函数的运算符:
m <- matrix(c(1:10, 11:20), nrow = 10, ncol = 2)
m %>% mean %>% sum
Ceci n&#39; est pas un pipe!