我想使用rollapply
函数与width
,by
和FUN
个参数的各种组合(width
和by
应该相同值)。我启发了here并创建了以下代码,但它与rollapply
无关,它只是演示如何将多个参数传递给apply
内的函数:
> dframe <- expand.grid(c(1,2,3), c(1,2,3))
> testFunc <- function(a, b) a^2 + b
> apply(dframe, 1, function(x) testFunc(x[1], x[2]))
[1] 2 5 10 3 6 11 4 7 12
> apply(dframe, 1, function(x) x[1]^2 + x[2])
[1] 2 5 10 3 6 11 4 7 12
> apply(dframe, 1, function(x) (x[1]^2 + x[2]))
[1] 2 5 10 3 6 11 4 7 12
> apply(dframe, 1, function(x) {x[1]^2 + x[2]})
[1] 2 5 10 3 6 11 4 7 12
我的最终解决方案就在这里,但这不起作用:
> dframe <- expand.grid(c(1,2,3), c(median, mean))
> testFunc <- function(a, b) rollapply(mtcars, width = a, by = a, FUN = b, align="left")
> apply(dframe, 1, function(x) testFunc(x[1], x[2]))
Error in get(as.character(FUN), mode = "function", envir = envir) :
object 'b' of mode 'function' was not found
> apply(dframe, 1, function(x) rollapply(mtcars, width = x[1], by = x[1], FUN = x[2], align="left"))
Error in match.fun(FUN) : 'x[2]' is not a function, character or symbol
当我直接打电话给testFunc
时,一切正常,所以我猜问题是apply
无法以某种方式收集结果:
> testFunc(10,mean)
mpg cyl disp hp drat wt qsec vs am gear carb
[1,] 20.37 5.8 208.61 122.8 3.538 3.1280 18.581 0.6 0.3 3.6 2.5
[2,] 19.89 6.6 259.25 149.6 3.552 3.6689 18.301 0.4 0.3 3.4 2.9
[3,] 20.39 6.2 228.25 152.6 3.654 2.8633 16.914 0.3 0.5 3.9 2.6
> class(testFunc(10,mean))
[1] "matrix"
我还试过调试testFunc
并从apply
调用它,看起来参数传递正确:
> debug(testFunc)
> apply(dframe, 1, function(x) testFunc(x[1], x[2]))
debugging in: testFunc(x[1], x[2])
debug: rollapply(mtcars, width = a, by = a, FUN = b, align = "left")
Browse[2]> print(a)
$Var1
[1] 1
Browse[2]> print(b)
$Var2
function (x, na.rm = FALSE)
UseMethod("median")
<bytecode: 0x08244ffc>
<environment: namespace:stats>
Browse[2]> n
Error in get(as.character(FUN), mode = "function", envir = envir) :
object 'b' of mode 'function' was not found
问题:
expand.grid
替换嵌套循环并调用inner
函数有多个参数?*apply
系列函数返回矩阵列表?PS:我想使用两个嵌套循环很容易实现这一点,但我想知道是否有R-way。
PPS:Here是类似错误(object 'b' of mode 'function' was not found
)的答案,其结论是b
(在我的情况下)与其他函数的命名参数冲突。但我在代码中看不到这个问题。
答案 0 :(得分:6)
假设df <- data.frame(a = 1:2, b = 3:4)
我们申请apply(df, 1, function(x) fun(x))
。然后两个传递的参数x
是向量 c(1, 3)
和c(2, 4)
。
但是,当df <- expand.grid(c(1,2,3), c(median, mean))
和apply(df, 1, function(x) fun(x))
完成后,我们无法再将1
和median
存储到单个向量中,因为它们的类型太不相同。然后x
恰好是列表,例如x <- list(1, median)
。然后,执行x[1]
或x[2]
不会根据需要提供1
和median
;相反,这些是具有单个元素的列表(因此错误object 'b' of mode 'function' was not found
)。实际上可以在调试示例中看到这一点。
因此,以下是一些在您的案例中使用apply
的方法:
1)不要修改testFunc
,但要认识到apply
传递了一个列表;在这种情况下,do.call
会有所帮助,但它也会关注df
列的名称,所以我也使用unname
:
apply(unname(df), 1, do.call, what = testFunc)
2)与1)相同但没有do.call
:
apply(dframe, 1, function(x) testFunc(x[[1]], x[[2]]))
3)testFunc
重新定义为只有一个参数:
testFunc <- function(a) rollapply(mtcars, width = a[[1]], by = a[[1]], FUN = a[[2]], align="left")
apply(dframe, 1, testFunc)