R语言拒绝采样绘制直方图报错:'x' is not numeric
解决拒绝采样函数导致的“'x' is not numeric”错误
你的代码出现这个错误的核心原因是:rexp_k函数在不满足接受条件时没有返回值,导致replicate生成的结果里混入了NULL,而hist无法处理包含非数值的向量。接下来我们一步步修复问题:
1. 修复函数的核心逻辑:循环直到采样成功
现在你的函数只尝试一次采样,不满足条件就返回空值。拒绝采样需要不断重复采样步骤,直到满足接受条件为止,所以要加一个while循环:
rexp_k <- function(a, b) { # 移除内部覆盖参数的代码,保留传入的a,b # 计算M:beta分布的峰值(未归一化的最大值,因为f/g是未归一化beta/均匀) mode <- (a-1)/(a+b-2) M <- (mode^(a-1)) * ((1-mode)^(b-1)) / dunif(mode) # dunif值为1,这里保留写法更清晰 while(TRUE) { y <- runif(1) u <- runif(1) f_unscaled <- (y^(a-1)) * ((1-y)^(b-1)) # 未归一化的beta密度 g <- dunif(y) # 均匀分布的密度,固定为1 if (u <= f_unscaled / (M * g)) { return(y) } } }
这里做了几个关键调整:
- 删掉了函数内部重新赋值
a <- 2.5和b <- 3.5的代码,让函数能使用传入的参数 - 用
while(TRUE)循环不断尝试采样,直到满足接受条件才返回结果,不会再出现空值 - 调整了接受条件的写法(和原逻辑等价,但更直观)
2. 验证采样结果并绘制直方图
现在运行采样代码:
a <- 2.5 b <- 3.5 beta_samples <- replicate(1000, rexp_k(a,b)) # 建议增加采样数量,让直方图更平滑 hist(beta_samples, probability = TRUE) # 可以叠加真实的beta分布曲线对比采样效果 curve(dbeta(x, a, b), add = TRUE, col = "red", lwd = 2)
这次beta_samples会是纯数值向量,hist就能正常运行了,还能直观看到采样结果和真实beta分布的拟合情况。
额外优化建议
- 函数名
rexp_k容易让人误解是指数分布采样,建议改成rbeta_rejection之类的名字,语义更清晰 - 直接用
dbeta(y,a,b)代替手动计算未归一化密度,代码更简洁且不易出错:rbeta_rejection <- function(a, b) { mode <- (a-1)/(a+b-2) M <- dbeta(mode, a, b) / dunif(mode) # M为beta密度的最大值 while(TRUE) { y <- runif(1) u <- runif(1) if (u <= dbeta(y, a, b) / (M * dunif(y))) { return(y) } } }
内容的提问来源于stack exchange,提问作者Yash Lapasia
相关产品推荐
相关产品推荐

