在R中使用for循环求和二项分布值时遇结果异常问题
问题
我正在开展一个项目,目标是对4个比例的6次抽样所有排列的二项分布值求和。我使用expand.grid生成了一个4096行×6列的tibble,并编写了看似正确的循环,但得到的结果比我计算的任何单个比例值都小。
我的比例如下:
w1 = 12/28 w2 = 17/27 w3 = 17/25 w4 = 21/26
生成tibble的代码:
one = c(w1, w2, w3, w4) two = c(w1, w2, w3, w4) thrr = c(w1, w2, w3, w4) four = c(w1, w2, w3, w4) five = c(w1, w2, w3, w4) six = c(w1, w2, w3, w4) tour = expand.grid(g1 = one, g2 = two, g3 = thrr, g4 = four, g5 = five, g6 = six)
使用的循环代码:
win = 0 for (i in length(tour)) { win = win + (dbinom(1, 1, prob = tour$g1[i])*dbinom(1, 1, prob = tour$g2[i])*dbinom(1, 1, prob = tour$g3[i])*dbinom(1, 1, prob = tour$g4[i])*dbinom(1, 1, prob = tour$g5[i])*dbinom(1, 1, prob = tour$g6[i])) }
运行循环后得到win = 0.01337406,这比很多单个计算值都小。单独运行以下代码时,我得到了正确的结果0.2776359:
dbinom(1, 1, prob = w4)*dbinom(1, 1, prob = w4)*dbinom(1, 1, prob = w4)*dbinom(1, 1, prob = w4)*dbinom(1, 1, prob = w4)*dbinom(1, 1, prob = w4)
说明一下,我的下一步是将求和结果乘以数值总数的倒数(1/4096),并非计算任意值。请问有什么解决建议?
解决建议
- 修正循环范围:你当前循环的
length(tour)返回的是数据框的列数(6),导致循环只执行了1次(仅计算第6行的乘积),这是结果偏小的核心原因。正确的循环范围应遍历所有行,改为for (i in 1:nrow(tour))。 - 简化二项分布计算:
dbinom(1, 1, prob = p)等价于p(单次试验成功1次的概率就是成功概率本身),可以直接用列值相乘,无需调用dbinom,简化代码的同时提升效率。 - 用向量化操作替代循环(更高效):R中向量化操作比循环速度更快,可直接计算每行乘积后求和,示例代码:
# 方法1:用apply计算每行乘积再求和 win = sum(apply(tour, 1, prod)) # 方法2:用dplyr处理 library(dplyr) win = tour %>% mutate(product = g1*g2*g3*g4*g5*g6) %>% pull(product) %>% sum()
修正后的循环代码示例:
win = 0 for (i in 1:nrow(tour)) { win = win + tour$g1[i] * tour$g2[i] * tour$g3[i] * tour$g4[i] * tour$g5[i] * tour$g6[i] }
最后计算平均值:
avg_win = win / 4096
内容的提问来源于stack exchange,提问作者Jericho Kirby
相关产品推荐
相关产品推荐

