R中lapply实现GLM自助抽样遇作用域问题:w未被识别原因
关于R中lapply+GLM自助抽样时公式定义位置导致权重无法识别的问题
问题重现
在R 4.3.0中用lapply做GLM的自助抽样时,遇到一个特殊问题:当把GLM的公式ff定义在匿名函数外部时,代码会报object 'w' not found的错误,但把公式放在函数内部就能正常运行。
可正常运行的代码(公式在函数内)
library(dplyr) data_adult <- read.csv("https://raw.githubusercontent.com/guru99-edu/R-Programming/master/adult.csv") data_adult$Y <- (data_adult$hours.per.week > 40) iest_boot <- lapply(1:10, function(bb){ ff <- as.formula('Y ~ gender') w <- rexp(nrow(data_adult), 1) glmout <- glm(ff, 'quasibinomial', data_adult, w) return(coef(glmout)) })
报错的代码(公式在函数外)
ff <- as.formula('Y ~ gender') iest_boot <- lapply(1:10, function(bb){ w <- rexp(nrow(data_adult), 1) glmout <- glm(ff, 'quasibinomial', data_adult, w) return(coef(glmout)) }) # 报错信息:Error in eval(extras, data, env) : object 'w' not found
问题原因
核心在于公式对象的环境绑定规则:
- 当你在全局环境定义
ff时,这个公式对象的默认绑定环境是全局环境(.GlobalEnv)。 glm在处理weights参数时,如果传入的是变量名(比如这里的w),它会优先在公式绑定的环境中查找这个变量,而不是当前函数的局部环境。- 你的
w是定义在lapply匿名函数内部的局部变量,全局环境中不存在这个对象,因此会触发找不到的错误。
而把ff放在匿名函数内部时,公式的绑定环境就是这个函数的执行环境,里面正好有定义好的w,所以能正常查找。
至于全局的data_adult能被识别,是因为R的作用域规则是从当前环境向上回溯查找,glm在处理数据参数时,会从匿名函数环境往上找到全局环境,自然能拿到这个数据集。
解决办法
有两种简单的解决方式:
- 保持公式在函数内部定义(就是你已经验证过的正常写法)。
- 如果一定要把公式放在外部,有两种子方案:
- 显式传入权重向量(写法更清晰直观):
ff <- as.formula('Y ~ gender') iest_boot <- lapply(1:10, function(bb){ w <- rexp(nrow(data_adult), 1) glmout <- glm(ff, 'quasibinomial', data_adult, weights = w) return(coef(glmout)) }) - 修改公式的绑定环境为当前函数环境:
ff <- as.formula('Y ~ gender') iest_boot <- lapply(1:10, function(bb){ environment(ff) <- environment() # 将公式环境切换到当前函数的局部环境 w <- rexp(nrow(data_adult), 1) glmout <- glm(ff, 'quasibinomial', data_adult, w) return(coef(glmout)) })
- 显式传入权重向量(写法更清晰直观):
内容的提问来源于stack exchange,提问作者The_Anomaly
相关产品推荐
相关产品推荐

