如何有效地生成模拟值的数据框?

And*_*rew 3 simulation r

我正在尝试根据现有的分布参数生成模拟值的数据框。我的主数据框包含每个观察值的平均值和标准差,如下所示:

\n\n
example.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\n
Run Code Online (Sandbox Code Playgroud)\n\n

我可以使用sapply()自定义函数来使用 Score_mean 和 Score_sd 参数从正态分布中随机抽取:

\n\n
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\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将生成一轮(或一列)模拟值。但是,我想生成很多列(例如 100 或 1,000)。我发现执行此操作的唯一方法是将我的sapply()函数包装在内部的通用函数中,然后使用inlapply()将结果列表转换为数据框ldply()plyr

\n\n
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\n
Run 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\n

有没有更有效的方法来创建这样的模拟值数据框?

\n

Sim*_*lon 5

我能想到的最快方法是利用rnorm. 和参数都是矢量化的,但是您只能为抽奖次数提供一个整数meansd如果您向meansd参数提供一个向量,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)