不在apply中传递所有可选参数

时间:2015-04-13 20:23:20

标签: r function

我在使用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 个答案:

答案 0 :(得分:4)

您可以使用Curry中的functional来修复所需的参数,将该函数放入要应用的函数列表中,最后遍历此函数列表:

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 :(得分:1)

我主张使用Colonel的Curry方法,但如果你想坚持基础R,你可以随时:

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

大致是Curry最终在做什么

答案 2 :(得分:0)

一种选择是使用每个函数所需的参数传递列表中的参数。您可以使用apply将这些参数添加到c所需的其他参数中,然后使用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)

答案 3 :(得分: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)