R:顺序地将具有自变量的函数的任意列表应用于矩阵

时间:2014-06-22 12:48:37

标签: r lapply

我有一个过滤函数列表f1,f2,f3,f4,....,它将矩阵m和许多选项作为输入,并返回矩阵行的子集作为输出。现在我希望能够以有序的方式定义一些元过滤功能设置metaf1, metaf2, metaf3,...,它将指定指定nr个过滤功能的顺序应用,例如,首先是f2,然后是f3,每个都使用给定的选项。我想将这些过滤设置存储在类"metafiltering"的列表中,然后让另一个函数应用给定metafiltering对象中指定的过滤步骤。我的想法是能够以这种方式允许以有序的方式存储和应用过滤设置。我将如何以最优雅的方式在R中实现这一目标?或者是否有其他方便的方法可以实现这样的目标?

编辑:举个例子,说我有矩阵

m=replicate(10, rnorm(20)) 

和过滤功能(这些只是示例,显然我的更复杂:-))

f1=function(m,opt1,opt2) { 
return(m[(m[,2]>opt1)&(m[,1]>opt2),])
}
f2=function(m,opt1) { 
return(m[(m[,3]>opt1),])
}

我已经定义了特定类的以下metafiltering设置,这些设置将指定必须顺序应用于矩阵m的两个函数

metafilterfuncs=list(fun1=f1(opt1=0.1,opt2=0.2),fun2=f2(opt1=0.5))
class("metafilterfuncs")="metafiltering"

我的问题是如何使用指定的函数和设置将任意metafiltering函数对象的过滤步骤应用于给定的矩阵m?

2 个答案:

答案 0 :(得分:2)

您可以这样做:

您可以定义一种函数pieplines,其中为每个函数赋予优先级。

pipelines <- c(f1=100,f2=300,f3=200)

我在这里定义了3个虚拟函数用于测试:

f1 <- function(m,a) m + a
f2 <- function(m,b) m + b
f3 <- function(m,c) m + c

对于每个函数,将参数存储在另一个列表中:

args <- list(f1=c(a=1),f2=c(b=2),f3=c(c=3))

然后你应用你的功能:

m <- matrix(1:2,ncol=2)
for (func in names(pipelines[order(pipelines)]))
{
  m <- do.call(func,list(m,args[[func]]))
}

答案 1 :(得分:1)

pryr有一个函数compose,就像你需要的那样,但它并没有完全削减它。 compose函数需要逐个给出函数,而不是列表,并且它不能接受参数。它也奇怪地放在那个包里。类似的功能可以在 plyr 中找到,即每个。但是这个函数不是按顺序应用函数,而是单独应用并输出一个命名向量(列表?)。

agstudy上面提供了一个解决方案,但它遇到了一个问题:它只能采用标量参数,因为它在命名向量中给出了参数。解决方案是使用命名列表。因此,这里有一个改进的功能来替换 pryr 中的那个。

compose2 = function(x, funcs, args, msg_intermediate = F) {
  if (length(funcs) != length(args)) stop("length of functions and arguments must match")
  for (i in seq_along(funcs)) {
    x = do.call(what = funcs[[i]], args = c(x, args[[i]]))
    if ((i != length(funcs)) && msg_intermediate) message(x)
  }
  x
}

msg_intermediate是一个很好的调试参数,可以向中间结果发送消息,因此可以更容易地理解会发生什么。

测试它:

adder = function(x, n) x + n
compose2(0,
         funcs = list(adder, adder, adder),
         args = list(list(n = 1), list(n = 2), list(n = 3)),
         msg_intermediate = T
         )

输出:

1
3
[1] 6

这是你取0,然后加1(= 1),然后加2(= 3),然后加3(= 6)得到的。

compose2的args参数采用列表列表,因此可以提供非标量函数参数。这是一个例子:

add_div = function(x, n, d) (x + n) / d
compose2(0,
         funcs = list(add_div, add_div, add_div),
         args = list(list(n = 1, d = 1), list(n = 2, d = 2), list(n = 3, d = 3)),
         msg_intermediate = T
)

输出:

1
1.5
[1] 1.5

当你取0,加1,除以1(= 1),然后取1,加2然后除以2(= 1.5),然后取1.5,加3然后除以3,得到的是(= 1.5)。