我试图尽可能多地减少一个函数的执行时间,该函数对伯努利序列序列的输出求和。
这是我的工作但很慢的方法:
set.seed(28100)
sim <- data.frame(result = rep(NA, 10))
for (i in 1:nrow(sim)) {
sim$result[i] <- sum(rbinom(1200, size = 1, prob = 0.2))
}
sim
# result
# 1 268
# 2 230
# 3 223
# 4 242
# 5 224
# 6 218
# 7 237
# 8 254
# 9 227
# 10 247
如果没有for-loop,我怎么能得到相同的结果?
我试过了......
set.seed(28100)
sim <- data.frame(result = rep(sum(rbinom(1200, size = 1, prob = 0.2)), 10))
sim
# result
# 1 269
# 2 269
# 3 269
# 4 269
# 5 269
# 6 269
# 7 269
# 8 269
# 9 269
# 10 269
但显然rep()
的论点只执行一次。
答案 0 :(得分:5)
二项分布定义为伯努利试验的总和。
# this line from your question
sum(rbinom(1200, size = 1, prob = 0.2))
# is equivalent to this
rbinom(1, size = 1200, prob = 0.2)
# and replicating it
replicate(expr = sum(rbinom(1200, size = 1, prob = 0.2)), n = 10)
# is equivalent to setting n higher:
### This is the only line of code you need! ####
rbinom(10, size = 1200, prob = 0.2)
在我的(相当慢的)笔记本电脑上进行100,000次模拟需要大约0.01秒,对于1M模拟需要0.12秒。
修改@ eipi的不错基准测试,这比其他方法快700-900倍(现在有bug修复!)
expr min lq mean median uq max neval cld
binom 1.324 1.377 1.607959 1.413 1.931 2.306 10 a
replicate 716.300 737.200 756.288641 749.900 765.300 812.400 10 b
sapply 706.300 743.300 778.863587 763.800 853.500 860.300 10 b
matrixColSums 838.800 870.000 893.813083 894.800 907.500 978.200 10 c
基准代码:
nn = 10000
n_bern = 1200
library(microbenchmark)
print(
microbenchmark::microbenchmark(
replicate =
replicate(nn, sum(rbinom(
n_bern, size = 1, prob = 0.2
)))
,
matrixColSums =
colSums(matrix(
rbinom(n_bern * nn, size = 1, prob = 0.2), ncol = nn
)),
sapply = sapply(
1:nn,
FUN = function(x) {
sum(rbinom(n_bern, size = 1, prob = 0.2))
}
),
binom = rbinom(nn, size = n_bern, prob = 0.2),
times = 10
),
order = "median",
signif = 4
)
答案 1 :(得分:2)
这样怎么样:
set.seed(28100)
sims <- 10
n <- 1200
r <- rbinom(n*sims, size = 1, prob = 0.2)
r <- matrix(r, ncol=sims)
colSums(r)
对我而言,它的速度是100,000次模拟速度的两倍(6 vs 13秒),但R. Schifini和eipi10解决方案速度更快(约5.5秒)
答案 2 :(得分:2)
set.seed(28100)
nsim=10
sim = data.frame(result=replicate(nsim, sum(rbinom(1200, size=1, prob=0.2))))
sim
result 1 268 2 230 ... 9 227 10 247
以下是使用10,000次模拟的各种方法的一些时间:
microbenchmark::microbenchmark(
replicate = {nsim=10000
data.frame(result=replicate(nsim, sum(rbinom(1200, size=1, prob=0.2))))},
matrixColSums = {
sims <- 10000
n <- 1200
r <- rbinom(n*sims, size = 1, prob = 0.2)
r <- matrix(r, ncol=sims)
data.frame(result=colSums(r)) },
sapply = data.frame(result=sapply(1:10000, FUN = function(x) {sum(rbinom(1200, size = 1, prob = 0.2))})),
times=10
)
Unit: milliseconds expr min lq mean median uq max neval cld replicate 584.2389 597.5571 615.7545 614.0977 630.7354 648.8328 10 a matrixColSums 655.0608 664.2053 684.0069 682.1868 702.1426 713.0240 10 b sapply 589.9830 610.5784 626.8738 629.2161 642.2589 660.6092 10 a
答案 3 :(得分:1)
执行以下操作:
sim = rep(NA, 10)
sapply(sim,FUN = function(x) {sum(rbinom(1200, size = 1, prob = 0.2))})
结果:
[1] 216 231 234 249 249 236 255 251 231 244
然后转换为数据框
答案 4 :(得分:0)
矢量化是关键。
主要节省时间(至少对于大n
)是sample
的使用。
e.g。为了
n <- 1e7
sample(0:1, n, replace=TRUE)
需要大约0.2秒,而
for(i in 1:n) sample(0:1, 1)
大约需要24秒。矢量化操作通常可以替换循环,但知道何时何地取决于对可用功能的熟悉程度。