You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:20:25