我正在尝试根据现有的分布参数生成模拟值的数据框。我的主数据框包含每个观察值的平均值和标准差,如下所示:
\n\nexample.data <- data.frame(country=c("a", "b", "c"), \n score_mean=c(0.5, 0.4, 0.6), \n score_sd=c(0.1, 0.1, 0.2))\n\n# country score_mean score_sd\n# 1 a 0.5 0.1\n# 2 b 0.4 0.1\n# 3 c 0.6 0.2\nRun Code Online (Sandbox Code Playgroud)\n\n我可以使用sapply()自定义函数来使用 Score_mean 和 Score_sd 参数从正态分布中随机抽取:
score.simulate <- function(score.mean, score.sd) {\n return(mean(rnorm(100, mean=score.mean, sd=score.sd)))\n}\n\nsimulated.scores <- sapply(example.data$score_mean, \n FUN=score.simulate, \n score.sd=example.data$score_sd)\n\n# [1] 0.4936432 0.3753853 0.6267956\nRun Code Online (Sandbox Code Playgroud)\n\n这将生成一轮(或一列)模拟值。但是,我想生成很多列(例如 100 或 1,000)。我发现执行此操作的唯一方法是将我的sapply()函数包装在内部的通用函数中,然后使用inlapply()将结果列表转换为数据框ldply()plyr:
results.list <- lapply(1:5, FUN=function(x) sapply(example.data$score_mean, FUN=score.simulate, score.sd=example.data$score_sd))\n\nlibrary(plyr)\nsimulated.scores <- as.data.frame(t(ldply(results.list)))\n\n# V1 V2 V3 V4 V5\n# V1 0.5047807 0.4902808 0.4857900 0.5008957 0.4993375\n# V2 0.3996402 0.4128029 0.3875678 0.4044486 0.3982045\n# V3 0.6017469 0.6055446 0.6058766 0.5894703 0.5960403\nRun Code Online (Sandbox Code Playgroud)\n\n这是可行的,但是(1)它看起来确实很复杂,特别是使用这种as.data.frame(t(ldply(lapply(... FUN=function(x) sapply ...))))方法,(2)当使用大量迭代或更大的数据\xe2\x80\x94时它真的很慢\xe2\x80\x94我的实际数据集有3,000行,运行1,000次迭代需要1\xe2\x80\x932 分钟。
有没有更有效的方法来创建这样的模拟值数据框?
\n我能想到的最快方法是利用rnorm. 和参数都是矢量化的,但是您只能为抽奖次数提供一个整数mean。sd如果您向mean和sd参数提供一个向量,R 将循环遍历它们,直到完成所需的绘制次数。因此,只需将参数n设为向量rnorm长度的倍数即可mean。乘数将是 data.frame 的每行的重复次数。在下面的函数中,这是n.
我想不出比base::rnorm单独使用更有效的方法。
#example data
df <- data.frame(country=c("a", "b", "c"),
mean=c(1, 10, 100),
sd=c(1, 2, 10))
#function which returns a matrix, and takes column vectors as arguments for mean and sd
normv <- function( n , mean , sd ){
out <- rnorm( n*length(mean) , mean = mean , sd = sd )
return( matrix( out , , ncol = n , byrow = FALSE ) )
}
#reproducible result (note order of magnitude of rows and input sample data)
set.seed(1)
normv( 5 , df$mean , df$sd )
# [,1] [,2] [,3] [,4] [,5]
#[1,] 0.3735462 2.595281 1.487429 0.6946116 0.3787594
#[2,] 10.3672866 10.659016 11.476649 13.0235623 5.5706002
#[3,] 91.6437139 91.795316 105.757814 103.8984324 111.2493092
Run Code Online (Sandbox Code Playgroud)