You need to enable JavaScript to run this app. R中存储方程右侧表达式计算对数似然时报未找到对象错误的咨询
优惠活动
大模型
产品
解决方案
定价
更多

R中存储方程右侧表达式计算对数似然时报未找到对象错误的咨询

报错核心原因

R对普通赋值语句的执行逻辑是即时求值:你写DA <- b0 + b1*x1 + ...的时候,R会立刻在当前全局环境里检索b0、b1、所有x和d开头的变量,把每个变量对应的数值代入计算出结果,再把这个数值存为DA——它不会自动把“由b和x/d组成的方程结构”当成可后续动态加载的公式存起来。
你现在还没有把待估计的系数b0、b1等定义成环境里存在的数值对象,自然会触发找不到b0的报错。

适配对数似然估计的可行解决方法

因为你要做的是动态调用DA计算对数似然,本质上需要DA能跟着优化器传入的待估系数动态变化,有两种完全适配需求的写法:

方法1:将方程结构存为可延迟求值的表达式

用expression()把方程的结构存下来,赋值时R不会当场检索变量、计算结果,等后续真正需要算DA的时候,再把待估系数、数据列放到临时环境里求值即可:

# 仅存储方程结构,不会触发报错
DA_expr <- expression(
  b0 + b1 * x1 + b4 * x4 + b5 * x5 + b6 * x6 + b8 * x8 +
    b9 * x9 + b10 * x10 + b11 * x11 + b12 * x12 + b13 * x13 + b15 * x15 +
    b17 * x17 + b18 * x18 + b19 * x19 + b20 * x20 + b21 * x21 + b25 * x25 + b27 * x27 + 
    bl2 * d2 + bl3 * d3 + bl5 * d5 + bl6 * d6 + bl7 * d7 +  bl8 * d8 + bl9 * d9 + 
    bl10 * d10 + bl11 * d11
)

搭配eval()在对数似然函数内部动态计算DA,示例逻辑:

log_lik <- function(par, dat) {
  # 按顺序给优化器传入的系数向量命名,和表达式里的变量名一一对应
  coef_names <- c("b0","b1","b4","b5","b6","b8","b9","b10","b11","b12",
                  "b13","b15","b17","b18","b19","b20","b21","b25","b27",
                  "bl2","bl3","bl5","bl6","bl7","bl8","bl9","bl10","bl11")
  coef_list <- as.list(par)
  names(coef_list) <- coef_names
  # 构建临时求值环境:同时放入系数和数据列,避免全局变量污染
  eval_env <- c(coef_list, as.list(dat))
  # 动态计算DA的值
  DA <- eval(DA_expr, envir = eval_env)
  # 代入你写的对数似然公式计算
  sum(log((pnorm(DA)^dat$y) * ((1 - pnorm(DA))^(1 - dat$y))))
}

方法2:在对数似然函数内部直接计算DA,不做全局提前赋值

全局环境下提前给DA赋值本身就不符合动态估计的逻辑——因为系数是随优化过程不断变化的,提前存的固定值DA根本没法跟着迭代更新。
更省心的写法是完全跳过全局单独给DA赋值的步骤,每次计算对数似然时在函数内部当场计算DA:

log_lik <- function(par, dat) {
  # 给系数向量命名
  names(par) <- c("b0","b1","b4","b5","b6","b8","b9","b10","b11","b12",
                  "b13","b15","b17","b18","b19","b20","b21","b25","b27",
                  "bl2","bl3","bl5","bl6","bl7","bl8","bl9","bl10","bl11")
  # 用with()自动加载数据列,减少重复写dat$的冗余
  DA <- with(dat, 
    par["b0"] + par["b1"]*x1 + par["b4"]*x4 + par["b5"]*x5 +
    par["b6"]*x6 + par["b8"]*x8 + par["b9"]*x9 + par["b10"]*x10 +
    par["b11"]*x11 + par["b12"]*x12 + par["b13"]*x13 + par["b15"]*x15 +
    par["b17"]*x17 + par["b18"]*x18 + par["b19"]*x19 + par["b20"]*x20 +
    par["b21"]*x21 + par["b25"]*x25 + par["b27"]*x27 + par["bl2"]*d2 +
    par["bl3"]*d3 + par["bl5"]*d5 + par["bl6"]*d6 + par["bl7"]*d7 +
    par["bl8"]*d8 + par["bl9"]*d9 + par["bl10"]*d10 + par["bl11"]*d11
  )
  sum(log((pnorm(DA)^dat$y) * ((1 - pnorm(DA))^(1 - dat$y))))
}
避坑提示
  • 不要直接把quote(你的表达式)存的结果放到全局环境运行,否则依然会触发找不到b0的报错,必须绑定到自建的临时环境再求值。
  • 你最初写的对数似然部分里,(1-pnorm(DA))^(1-y)的维度对齐要注意:直接写1-y如果y是来自数据框的向量,可能会出现长度不匹配的警告,明确写成1 - dat$y是最稳妥的。
  • 如果你的模型是标准Probit线性模型,不需要从零手算对数似然,直接用glm(y ~ x1 + x4 + ... , data = dat, family = binomial(link = "probit"))就能完成系数估计;如果是带特殊限定的自定义模型,上面的方法可以通用适配。

内容的提问来源于stack exchange,提问作者Maria Kamran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 22:15:03