我有一个可变长度的命名列表,包含函数
mFunc <- list(A = identity, B = exp)
我还有data.frame
个名称是mFunc
名称的超集:
dat <- data.frame(A = 1:3, B = 1:3, C = 1:3)
我想要做的是将mFunc
中的所有功能应用到dat
中的相应列。如果我愿意手工做,我会做
dat$A <- mFunc$A(dat$A)
dat$B <- mFunc$B(dat$B)
,预期结果如下:
# A B C
# 1 1 2.718282 1
# 2 2 7.389056 2
# 3 3 20.085537 3
我在考虑在mFunc
library(plyr)
dat[, names(mFunc)] <- llply(names(mFunc), function(n) mFunc[[n]](dat[[n]]))
给了我想要的结果。我想知道是否有更快(矢量化)的方法,而不使用隐式循环?
答案 0 :(得分:0)
<强>基准强>
继续讨论后,我使用llply
和lapply
解决方案做了一些基准测试:
library(dplyr)
library(tidyr)
library(microbenchmark)
makeTestData <- function(n, m = 10) {
ret <- matrix(1, m, n)
as.list(as.data.frame(ret))
}
d1e7 <- makeTestData(1e7)
d1e6 <- makeTestData(1e6)
d1e5 <- makeTestData(1e5)
d1e4 <- makeTestData(1e4)
(mb <- microbenchmark(dplyr_1e7 = llply(d1e7, sum),
base__1e7 = lapply(d1e7, sum),
dplyr_1e6 = llply(d1e6, sum),
base__1e6 = lapply(d1e6, sum),
dplyr_1e5 = llply(d1e5, sum),
base__1e5 = lapply(d1e5, sum),
dplyr_1e4 = llply(d1e4, sum),
base__1e4 = lapply(d1e4, sum),
unit = "s"))
# Unit: seconds
# expr min lq mean median uq max neval cld
# dplyr_1e7 0.516720538 0.589467527 0.684496553 0.626970606 0.713114314 1.50305854 100 d
# base__1e7 0.510537527 0.568317076 0.650109031 0.593912047 0.654385189 1.65846752 100 cd
# dplyr_1e6 0.498767583 0.574463177 0.678273933 0.614690247 0.695204388 1.22767911 100 d
# base__1e6 0.490427644 0.543392591 0.610153445 0.587542713 0.638059997 1.03797757 100 c
# dplyr_1e5 0.045505505 0.047664210 0.076620745 0.049840086 0.062213015 0.83327188 100 b
# base__1e5 0.043557401 0.046385212 0.079063845 0.050644790 0.079270672 0.54647818 100 b
# dplyr_1e4 0.004488338 0.004746704 0.005941600 0.004970133 0.005845892 0.03784612 100 a
# base__1e4 0.004290173 0.004527419 0.006759915 0.004698939 0.005140864 0.04752546 100 a
还有一些统计数据:
mb %>% group_by(expr) %>% summarise(mean = mean(time)) %>%
separate(expr, c("system", "size"), sep = "\\_+") %>%
spread(system, mean) %>% mutate(ratio = base / dplyr)
# Source: local data frame [4 x 4]
# size base dplyr ratio
# (chr) (dbl) (dbl) (dbl)
# 1 1e4 6759915 5941600 1.1377262
# 2 1e5 79063845 76620745 1.0318856
# 3 1e6 610153445 678273933 0.8995679
# 4 1e7 650109031 684496553 0.9497623
<强>结论强>
因此,base
解决方案对于大数据集快6%,对小数据集慢13%(!)。绝对两者的执行时间具有相同的幅度。因此,我可以接受使用同一个动词族的小延迟(即使存在:对我来说也不明显)。