数据:
data <- structure(list(index = c(1, 2, 3, 4, 5, 6),
hour = c(13, 13, 13, 1, 1, 1), minutes = c(31,
31, 32, 36, 36, 36)), class = "data.frame", row.names = c(1067L,
1069L, 1070L, 1072L, 1073L, 1074L))
使用do.call
:
func <- function(hourFilt, minutesFilt){
filt <- data[data$hour == hourFilt & data$minutes == minutesFilt, ]$idx
sum(filt)
}
do.call(func, list(hourFilt = 1:5, minutesFilt = 31:35))
我知道警告的含义:
警告消息: 1:在data $ hour == hourFilt中: 较长的物体长度不是较短的物体长度的倍数
但是我希望该函数被调用五次,而不仅仅是被调用一次,从而导致警告和错误的结果。
预期结果:
mapply(func, hourFilt = 1:5, minutesFilt = 31:35)
1 2 0 0 0
但是,我更喜欢使用do.call()
,因为它更快。
修改:添加意图
我想过滤特定时间的25k-200k行的数据集。对原始数据集的过滤将导致三行。对于这个结果,我想总结一个给定的变量-在这里:索引。该过程将重复数百次。因此,我调查了mapply()
,do.call()
。性能确实很重要,这就是为什么我更喜欢do.call()
。
答案 0 :(得分:3)
do.call
的目的不是多次运行一个函数(如mapply那样),而是一次在一个元素列表上运行一个函数。当使用大型列表并尝试将单个函数应用于列表的所有参数时,这非常实用。如果要创建一个表格,其中每一列都是列表的元素,则典型示例为do.call(cbind,list)
。
因此,当您运行do.call(func, list(hourFilt = 1:5, minutesFilt = 31:35))
时R正在运行
func(hourFilt = 1:5, minutesFilt = 31:35)
因此您得到了错误。列表中的所有元素都立即传递给func()
的参数。
我认为mapply()
可能是解决您问题的最佳方法。如果您担心性能,可以尝试使用mcmapply()
软件包中的parallel
,该软件包可以并行化计算(在Windows中不适用)。
corenum <- parallel::detectCores()-1
parallel::mcmapply(func,hourFilt=1:5,minutesFilt=31:35,mc.cores=corenum)
或者,如果您使用的是Windows,则更麻烦的parSapply()
可能适合您:
corenum <- parallel::detectCores()-1
cl<-parallel::makeCluster(corenum)
#export the objects so that the parallel sockets can use them
parallel::clusterExport(cl,c("func","hourFilt","minutesFilt","data"))
result<-parallel::parSapply(cl,1:length(hourFilt),function(i){
func(hourFilt[i],minutesFilt[i])
})
PS:对于您的数据集,预期结果应为0 0 0 0 0