r语言 - 如何有效地实现 dplyr do 调用 lmer 函数?



我有一个包含 ~400000 行的数据集,我正在尝试使用 R 中的dplyrdo调用提取lme4混合模型方差分量。 函数为:

myfunc <- function(dat) {
if (sum(!is.na(dat$value)) > 840) {  # >70% data present 
v = data.frame(VarCorr(lmer(value ~ 0 + (1|gid) + (1|trial:rep) + (1|trial:rep:block), data=dat)))
data.frame(a=round(v[1,4]/(v[1,4]+(v[4,4]/2)),2), b=round(v[1,4],2), c=round(v[4,4],2), n_obs=nrow(dat), na_obs=sum(is.na(dat$value))) 
} else { 
data.frame(a=NA, b=NA, c=NA, n_obs= nrow(dat), na_obs=sum(is.na(dat$value)))
}
}

在按四个分组变量对数据进行分组后,通过dplyrdo调用调用此函数。最后dplyr调用是:

system.time(out <- tst %>% group_by(iyear,ilocation,trait_id,date) %>% 
do(myfunc(.)))

现在,当此代码在 11000 行的较小测试数据帧上运行时,大约需要 25 秒。但是在一整套 443K 行上运行它大约需要 8-9 个小时才能完成,这非常慢。很明显,代码的一部分正在降低性能,但我似乎无法弄清楚是lmer部分还是dplyr导致速度变慢。我有一种感觉,函数处理矢量化操作的方式有问题,但不确定。我尝试在函数调用外部初始化"out"矩阵,但它并没有提高性能。
不幸的是,我没有一个较小的可重现数据集可以共享。但想听听你对如何使这段代码更有效率的想法。

解决方案:parallel包中的mclapply功能派上了用场。正如@gregor正确指出的那样,这可能是lmer放慢速度的部分。最后,我最终并行化了函数调用:

myfunc <- function(i) {
dat = tst[tst$comb==unique(tst$comb)[i],]  #comb is concatenated iyear,ilocation....columns
if (sum(!is.na(dat$value)) > 840) {  # >70% data present per column
v = data.frame(VarCorr(lmer(value ~ 0 + rand_factor + nested_random_factor), data=dat)))
data.frame(trait=unique(tst$comb)[i], a=round(v[1,4])/5, b=round(v[1,4],2), c=round(v[4,4],2), n_obs=nrow(dat), na_obs=sum(is.na(dat$value))) 
} else {
data.frame(trait=unique(tst$comb)[i], a=NA, b=NA, c=NA, n_obs= nrow(dat), na_obs=sum(is.na(dat$value))) 
}
}
#initialize an empty matrix
out <- matrix(NA,length(unique(tst$comb)),6)
## apply function in parallel. output is list
n_cores = detectCores() - 2
system.time(my.h2 <- mclapply(1:length(unique(tst$comb)),FUN = myfunc, mc.cores = n_cores))

一台 12 核 unix 机器需要 ~2 分钟才能完成。

最新更新