【发布时间】:2017-09-29 14:37:50
【问题描述】:
在编写代码时,我经常只是编写我想到的代码。虽然我认为我从一开始就学习了高效的 R 编码(例如,避免 for ... if 循环),但我的解决方案并不总是由性能驱动。不幸的是,有时知道什么是最有效的代码是至关重要的——我想学习这一点!
目前我正在模拟多个数据帧组合成一个列表。模拟之后,我需要第二个数据框,其中包含整个列表中所有列的平均值和 SD。 (这里的“模拟”表示某些变量是从其他数据帧中模拟/重新采样的,其他变量只是具有特定 b_0 的随机正态或二项分布值。为简洁起见,我省略了第一部分在这里重新采样。)
我的代码(参见下面的示例)完美地产生了预期的结果,但它似乎首先有点慢(我说的是真实的几个小时),其次是高度消耗 RAM(为此我暂时减少了列表中模拟dfs的数量)。
对于模拟,我知道在函数中定义 data.frame 可能是一个问题,但我不知道如何做得更好。对于均值/SD 数据帧,我只能说它更慢。
如何提高代码的性能?谁能提供一些关于这种性能提升的基本规则(或相关信息来源)?
(我正在使用 R 3.x/64 和 Win 7/64 AMD FX(tm)-8350 八核处理器,4 GHz,16 GB 机器。CPU 在运行时保持相当凉爽,RAM在它的极限中呻吟。)
这里我给出一个用 cmets 测量系统时间的示例代码:
# definitions
r <- 1e5 # number of rows
n <- 1e3 # number of dfs
# simulation of the list
library(dplyr)
system.time(list <- lapply(1:n, function(i){ # 59.05 sec
data.frame(a = rbinom(r, 1, .375)) %>%
mutate(
b = rnorm(r, 0, 2),
c = .42 * rnorm(r, 0, 6),
d = rbinom(r, 11, c(1:11)/11),
e = rbinom(r, 1, .1),
f = .02 * rnorm(r, 0, 5))
}))
# df w/ means & sds
system.time(list.s <- data.frame( # 73.20 sec
list.mean = round(rowMeans(sapply(list, colMeans)), 2),
list.sd = round(sapply(do.call(rbind, list), sd), 2)))
【问题讨论】:
-
我不知道你在模拟什么,但你应该花一些时间考虑一下算法。无论如何,为什么在循环中调用 rnorm/binom?之后在 split 返回向量中调用一次。
-
该示例是调查模拟的一部分。考虑 e。 G。 'a' 作为治疗变量,'d' 作为孩子的数量,'e' 成员资格,'b','c','f' 一些随机正态分布效应。为了简洁起见,我在这里排除了参数和公式。你能最终澄清你的提议吗?
标签: r performance simulation resampling