R语言期望计算优化:替代低效循环并按列存储结果
优化方案:向量化运算替代循环
首先,R的核心优势是向量化运算,完全不需要用循环处理10万次迭代。下面分两种方案解决你的问题:
方案一:利用数学公式直接计算期望值(最优)
你的代码本质是计算二项分布下的期望收益,而二项分布的期望有现成公式,不需要逐次计算再求和:
- 设单次抽奖中奖概率为
p = Number.of.draws.year / Raffle.tickets.cap - 若购买
N张彩票(对应原代码中的size=N),则中奖次数的期望是N*p - 每张中奖彩票收益200,总期望收益就是
200 * N * p
用这个公式可以直接生成所有N对应的结果,速度极快:
# 定义参数 Number.of.draws.year <- 4032 Raffle.tickets.cap <- 4000000000 p <- Number.of.draws.year / Raffle.tickets.cap # 生成要测试的N序列(示例:1到100000的整数,可根据需求调整seq参数) N_seq <- seq(from = 1, to = 100000, by = 1) # 计算每个N对应的期望收益 expected_values <- 200 * N_seq * p # 转为数据框: # 方式1:10万列的结构(不推荐,内存占用极高) E.value.tickets.df <- as.data.frame(t(expected_values)) colnames(E.value.tickets.df) <- paste0("N_", N_seq) # 方式2:更合理的两列结构(N值+对应期望,节省内存且易分析) E.value.tickets.df <- data.frame(N = N_seq, Expected_Value = expected_values)
方案二:向量化计算原循环逻辑(若需保留逐项计算)
如果必须保留原逻辑(比如后续要扩展计算其他项),可以用向量化的dbinom结合sapply,避免手动循环:
# 定义参数 Number.of.draws.year <- 4032 Raffle.tickets.cap <- 4000000000 p <- Number.of.draws.year / Raffle.tickets.cap # 生成测试序列 N_seq <- seq(from = 1, to = 100000, by = 1) # 定义单N的计算函数 compute_expected <- function(N) { i <- 1:N prob <- dbinom(i, size = N, prob = p) gain <- i * 200 sum(prob * gain) } # 批量计算所有N的结果 expected_values <- sapply(N_seq, compute_expected) # 转为数据框(推荐两列结构) E.value.tickets.df <- data.frame(N = N_seq, Expected_Value = expected_values)
关键注意事项
- 生成10万列的数据框会占用大量内存,除非有特殊业务需求,否则优先选择N值与期望对应的两列结构,既节省内存又便于后续分析。
- 方案一的数学公式是最优解,计算速度比方案二快几个数量级,完全不会出现环境崩溃的问题。
内容的提问来源于stack exchange,提问作者L.at.happy.kinda
相关产品推荐
相关产品推荐

