【发布时间】:2014-04-23 22:54:27
【问题描述】:
我正在尝试根据现有分布参数生成模拟值的数据框。我的主要数据框包含每个观察值的平均值和标准差,如下所示:
example.data <- data.frame(country=c("a", "b", "c"),
score_mean=c(0.5, 0.4, 0.6),
score_sd=c(0.1, 0.1, 0.2))
# country score_mean score_sd
# 1 a 0.5 0.1
# 2 b 0.4 0.1
# 3 c 0.6 0.2
我可以使用sapply() 和自定义函数来使用 score_mean 和 score_sd 参数从正态分布中随机抽取:
score.simulate <- function(score.mean, score.sd) {
return(mean(rnorm(100, mean=score.mean, sd=score.sd)))
}
simulated.scores <- sapply(example.data$score_mean,
FUN=score.simulate,
score.sd=example.data$score_sd)
# [1] 0.4936432 0.3753853 0.6267956
这将生成一轮(或一列)模拟值。但是,我想生成很多列(如 100 或 1,000)。我发现这样做的唯一方法是将我的 sapply() 函数包装在 lapply() 内的通用函数中,然后将结果列表转换为带有 ldply() 在 plyr 中的数据框:
results.list <- lapply(1:5, FUN=function(x) sapply(example.data$score_mean, FUN=score.simulate, score.sd=example.data$score_sd))
library(plyr)
simulated.scores <- as.data.frame(t(ldply(results.list)))
# V1 V2 V3 V4 V5
# V1 0.5047807 0.4902808 0.4857900 0.5008957 0.4993375
# V2 0.3996402 0.4128029 0.3875678 0.4044486 0.3982045
# V3 0.6017469 0.6055446 0.6058766 0.5894703 0.5960403
这可行,但是 (1) 看起来确实很复杂,尤其是使用 as.data.frame(t(ldply(lapply(... FUN=function(x) sapply ...)))) 方法时,(2) 使用大量迭代或更大的数据时它真的很慢——我的实际数据集有 3,000 行,运行 1,000迭代需要 1-2 分钟。
有没有更有效的方法来创建这样的模拟值数据框?
【问题讨论】:
-
您可能不想从现有数据框中获取值,而是从向量中获取它们。然后创建新的向量。之后,将它们放回数据框中。这样,R 就不必花时间搜索数据框来获取值。
-
所以手动提取感兴趣的列,比如
scores.mean <- example.data$score_mean? -
你的意思是
lapply( 1:nrow(df) , function(i) rnorm( 3 , df[i,'mean'] , sd=df[i,'sd'] ) )? (df是example.data)。要随机使用平均值和标准差,您可以将lapply的第一个参数中的1:nrow(df)替换为sample( 1:nrow(df) , n , TRUE )以使用随机行(带替换)。 -
附注在您的示例中,将
results.list变成data.frame和as.data.frame( results.list )就足够了!! (data.frame本质上是一个基于列表的结构本身)。 -
我使用
Rcpp模拟了大型n,如果你的函数足够简单,那么易于编写和加速是很重要的。
标签: r simulation