如何用R计算非独立同分布抛硬币的各正面次数概率?
解决方案
你遇到的是泊松二项分布的问题,它专门用于计算n次独立但单次成功概率不同的伯努利试验中,恰好出现m次成功(此处即正面)的概率,完美匹配你的需求。
方法一:使用poibin包(推荐)
- 先安装并加载包:
install.packages("poibin") library(poibin)
- 单组概率计算示例:
针对你给出的prob = c(0.3, 0.2, 0.5),直接调用dpoibin函数即可得到所有正面次数的概率:
prob <- c(0.3, 0.2, 0.5) # 计算0到3次正面的概率 result <- dpoibin(x = 0:length(prob), p = prob) result
运行后会返回长度为4的向量,分别对应0、1、2、3次正面的概率,和你硬编码的结果完全一致,且自动保证概率总和为1。
- 批量处理10万组数据:
假设你的数据集是一个列表prob_list,每个元素是一组抛币的正面概率向量,用lapply即可批量计算:
# 示例:生成10万组模拟数据(每组抛币次数k从2到10不等) set.seed(123) prob_list <- replicate(100000, runif(sample(2:10, 1), 0, 1), simplify = FALSE) # 批量计算每组的各正面次数概率 all_results <- lapply(prob_list, function(p) dpoibin(x = 0:length(p), p = p))
all_results中的每个元素,就是对应组的0到k次正面的概率向量。
方法二:手动递归计算(无外部包依赖)
如果不想安装额外包,可通过递推公式手动实现泊松二项分布的概率计算:
poibin_density <- function(probs) { n <- length(probs) # 初始化概率向量,dp[1]对应0次成功,dp[i]对应i-1次成功 dp <- numeric(n + 1) dp[1] <- 1 for (p in probs) { # 从后往前更新,避免覆盖未使用的中间值 dp <- c(dp[1] * (1 - p), dp[-1] * (1 - p) + dp[-length(dp)] * p) } return(dp) } # 测试示例 prob <- c(0.3, 0.2, 0.5) poibin_density(prob)
这个函数同样能返回0到n次成功的概率,适合不想依赖外部包的场景,处理10万组数据的效率也完全达标。
内容的提问来源于stack exchange,提问作者David D
相关产品推荐
相关产品推荐

