emmeans在函数外正常运行,函数内报错‘datin未找到’(作用域问题?)
问题:emmeans在自定义函数内调用报错,外部运行正常的原因及解决方法
复现代码如下:
testdat = data.frame(y=c(1,2,3,4,5,6), x=c("A","A","A","B","B","B"), id=c("X","X","Y","X","X","Y")) test = function(datin){ model=aov(y~x+Error(id), data = datin) print(summary(model)) # 执行emm步骤时返回错误:"Error in eval(cl) : object 'datin' not found" emm=emmeans::emmeans(model,~x) return(emm) } test(testdat) # 此处无报错 model=aov(y~x+Error(id), data = testdat) summary(model) emm=emmeans::emmeans(model,~x) emm
原因分析
在自定义函数内部用aov()结合Error()拟合模型时,模型对象的调用记录(model$call)会保留data = datin的变量引用,但datin是函数的局部变量,仅存在于函数的执行环境中。当emmeans试图根据模型调用获取数据时,默认会在全局环境查找datin,自然找不到该变量,因此抛出报错。
而在全局环境拟合模型时,testdat是全局变量,emmeans能直接定位到数据,所以运行正常。
解决方法
提供两种简单可行的方案:
方案1:调用emmeans时显式指定data参数
直接在emmeans()中传入函数的局部数据datin,避免它去查找变量引用:
test = function(datin){ model=aov(y~x+Error(id), data = datin) print(summary(model)) # 显式指定data参数 emm=emmeans::emmeans(model,~x, data = datin) return(emm) }
方案2:让模型在数据的环境中拟合
用with()函数将模型拟合过程包裹在datin的环境中,使模型调用记录直接包含数据内容,而非变量引用:
test = function(datin){ # 用with在datin的环境中拟合模型 model = with(datin, aov(y~x+Error(id))) print(summary(model)) emm=emmeans::emmeans(model,~x) return(emm) }
内容的提问来源于stack exchange,提问作者Nicholas Root
相关产品推荐
相关产品推荐

