在使用apply函数时没有传递所有可选参数

9
我在使用apply函数时遇到了一些问题,它会将不需要的参数传递给函数。我知道apply不知道如何处理可选参数,只是将它们传递给函数。
但无论如何,这就是我想做的事情:
首先,我想指定一个我想要使用的函数列表。
functions <- list(length, sum)

我想创建一个函数,将这些指定的函数应用于数据集。
myFunc <- function(data, functions) {
  for (i in 1:length(functions)) print(apply(X=data, MARGIN=2, FUN=functions[[i]]))
}

这个很好用。
data <- cbind(rnorm(100), rnorm(100))
myFunc(data, functions)

[1] 100 100
[1] -0.5758939 -5.1311173

但我也想为一些函数使用额外的参数,例如:

power <- function(x, p) x^p 

它们并不按照我的预期工作。如果我修改myFunc为:

myFunc <- function(data, functions, ...) {
  for (i in 1:length(functions)) print(apply(X=data, MARGIN=2, FUN=functions[[i]], ...))
}

functions作为

functions <- list(length, sum, power)

当我尝试使用我的函数时,我得到了以下结果。
myFunc(data, functions, p=2)

Error in FUN(newX[, i], ...) : 
  2 arguments passed to 'length' which requires 1

我该如何解决这个问题?

很抱歉文字有点多。谢谢!

4个回答

4

您可以使用functional中的Curry来固定要处理的参数,将该函数放入您想要应用的函数列表中,最后迭代这个函数列表:

library(functional)

power <- function(x, p) x^p 
funcs = list(length, sum, Curry(power, p=2), Curry(power, p=3))
lapply(funcs, function(f) apply(data, 2 , f))

通过您的代码,您可以使用以下功能:

functions <- list(length, sum, Curry(power, p=2))
myFunc(data, functions)

1

我建议使用Colonel的Curry方法,但如果你想坚持使用基本的R语言,你也可以这样做:

funcs <- list(length, sum, function(x) power(x, 2))

这大致是Curry最终所做的。


0
一种选择是将参数作为列表传递,其中包含每个函数所需的参数。您可以使用 c 将这些参数添加到 apply 所需的其他参数中,然后使用 do.call 调用该函数。就像这样。我在此处还将所有输出都包装在列表中,而不是使用 print ; 您的用法可能会有所不同。
power <- function(x, p) x^p 
myFunc <- function(data, functions, parameters) {
  lapply(seq_along(functions), function(i) {
      p0 <- list(X=data, MARGIN=2, FUN=functions[[i]])
      do.call(apply, c(p0, parameters[[i]]))
  })
}

d <- matrix(1:6, nrow=2)
functions <- list(length, sum, power)
parameters <- list(NULL, NULL, p=3)
myFunc(d, functions, parameters)

0

您可以使用lazyeval包:

library(lazyeval)


my_evaluate <- function(data, expressions, ...) {
  lapply(expressions, function(e) {
    apply(data, MARGIN=2, FUN=function(x) {
      lazy_eval(e, c(list(x=x), list(...))) 
    })
  })
}

使用方法如下:

my_expressions <- lazy_dots(sum = sum(x), sumpow = sum(x^p), length_k = length(x)*k )
data <- cbind(rnorm(100), rnorm(100))
my_evaluate(data, my_expressions, p = 2, k = 2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接