我正在为大学做一个项目,它模拟了一个6/49的乐透幸运游戏.

通过 Select 1到49之间的6个不同数字来创建票证. 我必须模拟10^6张彩票,并将其与幸运彩票进行比较. 我想找出一张随机彩票的6个数字和幸运彩票的6个数字相交的基数.但如果我为10^6张彩票做一次,那么拥有一张与幸运彩票完美匹配的彩票的概率很低.所以我试着用10^6张随机的新彩票做这个过程"nr_esantion"次,然后取平均值.

以下是我的批评:

nr_esantion<-30
es<-10^6
nr_49<-1:49

table_1 <- rep(0,7)
table_1
for(i in 1:nr_esantion)
{
  lucky <- sample(nr_49,6,replace=FALSE)


inters <- replicate(es,length(intersect(sample(nr_49,6,replace=FALSE),lucky)),simplify="array")


aux <- array(table(inters))


# There are situations in which at one step "i", there are no intersections of cardinal 5 or 6.
if(length(aux)==5)
{
  aux <- c(aux,0,0)
}
else{
if(length(aux)==6)
{
  aux <- c(aux,0)
}
}

table_1 <- table_1+aux

}

table_1 <- table_1/nr_esantion

我对我得到的结果很满意,但我的问题是,对于10^6美元的门票来说,一次迭代大约需要20秒.因此,对于总共30次迭代来说,大约需要10分钟.对于某些项目任务,我必须将"nr_esantion"更改为300.

我的问题是:有没有更快的方法来计算这些$10^6*300$的样本?

推荐答案

这将使其速度提高超过一个数量级(您也可以并行执行此操作):

set.seed(895636177)
nr_esantion <- 30L
es <- 1e6L
nr_49 <- 49L

library(Rcpp算法s) # for `permuteSample`

table_1 <- integer(6)

system.time({
  for (i in 1:nr_esantion) {
    lucky <- sample(nr_49, 6)
    table_1 <- table_1 + tabulate(
      rowSums(
        matrix(match(permuteSample(nr_49, 6, n = es), lucky, 0L), es, 6) != 0L
      ), 6
    )
  }
  
  table_1 <- c(nr_esantion*es - sum(table_1), table_1)
})
#>    user  system elapsed 
#>   22.00    1.16   24.11

table_1
#> [1] 13079255 12390731  3970451   530064    28966      529        4

将模拟结果与准确分布进行比较:

cbind(
  Matches = 0:6,
  Simulation = table_1/nr_esantion/es,
  Exact = dhyper(0:6, 6, nr_49 - 6, 6)
)
#>      Matches   Simulation        Exact
#> [1,]       0 4.359752e-01 4.359650e-01
#> [2,]       1 4.130244e-01 4.130195e-01
#> [3,]       2 1.323484e-01 1.323780e-01
#> [4,]       3 1.766880e-02 1.765040e-02
#> [5,]       4 9.655333e-04 9.686197e-04
#> [6,]       5 1.763333e-05 1.844990e-05
#> [7,]       6 1.333333e-07 7.151124e-08

解释

这里的加速目标是对每个模拟复制进行矢量化.注意,replicatenot矢量化的.它本质上是for循环的包装器.

对于在没有替换的情况下重复从固定总体中提取n个样本,Rcpp算法s::permuteSample将比使用replicate所能做的任何事情都要快.

如果intersecty参数不变,那么对矩阵的单个match调用将比对矩阵的每一行调用intersect快得多.这是可行的,因为所有采样都是在没有替换的情况下完成的.match之后需要对不匹配项进行比较,将其整形为一个矩阵,然后求出行和.所有这些操作都是矢量化的,速度会非常快.

tabulatetable快,特别是在您知道数据中的最大整数的情况下(作为额外的好处,以这种方式调用Tablate将产生一个长度等于nbins参数的向量.

最后,使用整数和浮点数之间的速度差异很小(事实上,有时整数运算比浮点运算慢,因为R必须执行判断).但是对于大型数据集,整数的内存效率是原来的两倍.

R相关问答推荐

如何使用rmarkdown和kableExtra删除包含折叠行的表的第一列的名称

使用R中的Shapetime裁剪格栅文件

根据R中两个变量的两个条件删除带有dspirr的行

使用R中相同值创建分组观测指标

将年度数据插入月度数据

R中的子集文件—读取文件名索引为4位数字序列,例如0001到4000,而不是1到4000)

derrr summarise每个组返回多行?

标识R中多个列中缺少的唯一值

在RStudio中堆叠条形图和折线图

计算满足R中条件的连续列

在使用tidyModels和XGBoost的二进制分类机器学习任务中,所有模型都失败

以相同的方式对每个表进行排序

调换行/列并将第一行(原始数据帧的第一列)提升为标题的Tidyr类似功能?

如何为混合模型输出绘制不同的线型?

快速合并R内的值

如何调整一个facet_work()面板内的框图和移动标签之间的水平宽度?

在鼠标悬停时使用Plotly更改geom_point大小

是什么打破了此Quarto仪表板中的工具提示?

将每晚的平均值与每晚的值进行比较,统计是否有效?

如何使用包含要子集的值的列表或数据框来子集多个列?