问题 将n个函数的列表应用于数据帧的每一行?


我有一个功能列表

funs <- list(fn1 = function(x) x^2,
             fn2 = function(x) x^3,               
             fn3 = function(x) sin(x),
             fn4 = function(x) x+1)
#in reality these are all f = splinefun()

我有一个数据帧:

mydata <- data.frame(x1 = c(1, 2, 3, 2),
                     x2 = c(3, 2, 1, 0),
                     x3 = c(1, 2, 2, 3),
                     x4 = c(1, 2, 1, 2))
#actually a 500x15 dataframe of 500 samples from 15 parameters

对于每一个 一世 行,我想评估功能 Ĵ 每一个 Ĵ 列和总结结果:

unlist(funs)
attach(mydata)
a <- rep(NA,4)
for (i in 1:4) {
     a[i] <- sum(fn1(x1[i]), fn2(x2[i]), fn3(x3[i]), fn4(x4[i]))
}

我怎样才能有效地做到这一点?这是适当的实施机会吗? plyr 功能?如果是这样,怎么样?

奖金问题:为什么 a[4]  NA

这是使用函数的合适时间吗? plyr如果是的话,我怎么能这样做?


5822
2018-01-21 23:48


起源

@abe为第三个代码片段,你需要 unlist(funs) 和 attach(mydata) 或使用 funs$fn1 和 mydata$x1 - David LeBauer
@David感谢您的纠正,我已经更改了代码以反映这一点 - 但这正是我想要避免的混乱。 - Abe
好吧,对于奖励点,答案是mydata $ x4中没有第4个元素或该数据帧的任何列。进一步评论..简单地输入unlist(funs)除非你将结果分配给某些东西,否则什么都不做。欢迎来到函数式编程。 - 42-
注意 x1[i] 是数据框,而不是矢量。你要 x1[[i]] 要么 x1[, 1] - hadley
@hadley;不,x1 [1]是附加data.frame的一部分,它是长度为1的数字向量。 str(x1[1]) 返回num 1 - 42-


答案:


忽略您的代码段并坚持您要应用函数的初始规范 Ĵ 在列号上 Ĵ 然后“总结结果”......你可以这样做:

mapply( do.call, funs, lapply( mydata, list))
#      [,1] [,2]      [,3] [,4]
# [1,]    1   27 0.8414710    2
# [2,]    4    8 0.9092974    3
# [3,]    9    1 0.9092974    3

我不确定你现在想要以哪种方式添加结果(即行方式或列方式),所以你可以这样做 rowSums 要么 colSums 在这个矩阵上。例如:

colSums( mapply( do.call, funs,  lapply( mydata, list)) )
# [1] 14.000000 36.000000  2.660066  8.000000

9
2018-01-22 00:42



谢谢你的帮助;我将使用rowSums但这是我正在寻找的概念。 - Abe
我不明白最后一个列表的作用,是不是第二个参数do.call函数的参数列表? - Abe
我稍微编辑了上面的第二个表达式(你不需要这样做) as.list )。你确实需要这样做 lapply( mydata, list) 转 mydata 到列表中。然后 mapply 原因 do.call 采取每个功能 funs,并采取相应的列表成员 lapply(mydata,list),这本身就是一个清单。 - Prasad Chalasani
我刚刚有机会实现这个,而且system.time()$ elapsed是0.02秒,从实现为for循环时的2.5秒开始!谢谢你的帮助! - Abe


为什么不为所有4编写一个函数并将其应用于数据框? 你的所有功能都是矢量化的,所以也是 splinefun,这将工作:

fun <-  function(df)
    cbind(df[, 1]^2, df[, 2]^3, sin(df[, 3]), df[, 4] + 1)

rowSums(fun(mydata))

这比在行上“强制”或“应用”要高效得多。


4
2018-01-22 14:13





我试过用 plyr::each

library(plyr)
sapply(mydata, each(min, max))
    x1 x2 x3 x4
min  1  0  1  1
max  3  3  3  2

它工作正常,但当我通过自定义函数时,我得到:

sapply(mydata, each(fn1, fn2))
Error in proto[[i]] <- fs[[i]](x, ...) :
  more elements supplied than there are to replace

each 有非常简短的文档,我不太明白这是什么问题。


0
2018-01-22 19:07