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

在R函数中调用glm时无法找到环境内公式的问题求助

R中glm模型update时找不到公式的问题解决

问题原因

在fun2的局部环境中创建公式fmla并拟合glm模型时,公式对象会绑定当前的函数执行环境(即fun2的局部环境)。当fun2执行完毕返回后,这个局部环境会被R的垃圾回收机制清理。后续在fun1中调用update函数时,需要重新评估模型的公式,但此时公式绑定的环境已不存在,因此触发object 'fmla' not found错误。

你尝试的environment(fmla) <- environment()无效,是因为该语句仍将公式绑定到fun2的局部环境,并未解决后续环境被回收的问题。而使用<<-赋值虽然能运行,但会将fmla写入全局环境,污染全局命名空间,多次调用会覆盖全局变量,存在潜在bug。

解决方案

方案1:在fun1中直接重新拟合模型(推荐)

放弃使用update,直接提取原模型的公式,在训练集上重新拟合,彻底规避环境依赖问题:

n <- 20
ncov <- 3
df <- as.data.frame(replicate(ncov+1, runif(n)))
names(df) <- c(paste0("x", seq(ncov)), "y")

fun1 <- function(mod, pTrain = 0.5){
  data <- mod$data
  train <- sample(nrow(data), size = nrow(data)*pTrain)
  valid <- -train
  # 提取原模型公式,在训练集重新拟合
  modTrain <- glm(formula = formula(mod), data = data[train,])
  yhat <- predict(modTrain, newdata = data[valid,])
  # 修正原代码的长度不匹配问题:仅保留验证集的真实y值
  res <- data.frame(y = data$y[valid], yhat = yhat)
  return(res)
}

fun2 <- function(useCovs = c(1,0,0), data = df){
  fmla <- formula(paste("y ~", paste(paste0("x", seq(useCovs))[as.logical(useCovs)], collapse = " + ")))
  mod <- glm(formula = fmla, data = data)
  res <- fun1(mod, pTrain = 0.5)
  score <- sqrt(mean((res$y - res$yhat)^2))
  return(c(aic = AIC(mod), rmse = score))
}

fun2(useCovs = c(1,0,1)) # 正常运行

方案2:绑定公式到全局环境(不推荐)

若坚持使用update,可将公式的环境设置为全局环境,确保后续调用时变量可被找到,但此方法会污染全局命名空间:

fun2 <- function(useCovs = c(1,0,0), data = df){
  fmla <- formula(paste("y ~", paste(paste0("x", seq(useCovs))[as.logical(useCovs)], collapse = " + ")))
  environment(fmla) <- .GlobalEnv # 将公式环境绑定到全局
  mod <- glm(formula = fmla, data = data)
  res <- fun1(mod, pTrain = 0.5)
  score <- sqrt(mean((res$y - res$yhat)^2))
  return(c(aic = AIC(mod), rmse = score))
}

方案3:直接传递公式字符串给glm

构造公式字符串并直接传入glm,glm会自动解析为公式并绑定到数据环境,避免依赖函数局部环境:

fun2 <- function(useCovs = c(1,0,0), data = df){
  fmla_str <- paste("y ~", paste(paste0("x", seq(useCovs))[as.logical(useCovs)], collapse = " + "))
  mod <- glm(formula = fmla_str, data = data)
  res <- fun1(mod, pTrain = 0.5)
  score <- sqrt(mean((res$y - res$yhat)^2))
  return(c(aic = AIC(mod), rmse = score))
}

内容的提问来源于stack exchange,提问作者Marc in the box

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:32:33