predict.lme无法识别函数内变量定义的公式问题求助
解决predict.lme无法识别嵌套函数中动态定义公式的问题
问题根源
你遇到的错误是因为lme模型对象会保留拟合时的调用表达式(fit@call$fixed存储的是变量名fixForm而非实际公式),而predict.lme在执行时,会尝试在当前环境中查找fixForm变量。由于fixForm是train_test_perf函数的局部变量,函数执行完毕后局部环境被销毁,导致predict无法找到该变量。
解决方案(保留嵌套函数结构)
以下两种方法都能解决问题,且无需改变你的嵌套函数架构:
方法1:修改模型调用中的fixed参数为实际公式
拟合模型后,手动将模型对象的call$fixed替换为实际的公式对象,这样predict时会直接使用公式而非查找变量:
train_test_perf <- function(train_data, test_data, model, termLabels) { fixForm <- reformulate(termlabels=termLabels, response="Y") fit <- nlme::lme(fixForm, data=train_data, random=~ 1|ID) # 关键:将模型调用中的fixed参数替换为实际公式 fit@call$fixed <- fixForm train_pred <- predict(fit, newdata=train_data, level=0, na.action=na.exclude) rtrain <- cor.test(train_data$Y, train_pred) test_pred <- predict(fit, newdata=test_data, level=0, na.action=na.exclude) rtest <- cor.test(test_data$Y, test_pred) tmp <- data.frame(Model=model, R_train=rtrain$estimate, R_test=rtest$estimate) return(tmp) } # 外层函数和调用保持不变 myfunc <- function(df, newdf, varList) { for (v in varList) { perf <- train_test_perf(train_data=df, test_data=newdf, model=v, termLabels=v) print(perf) } } myfunc(df=dat, newdf=newdat, varList=list("W", "X"))
方法2:直接创建带全局环境的公式
跳过reformulate,直接用字符拼接生成公式,并显式指定公式的环境为全局环境,避免predict时的环境查找问题:
train_test_perf <- function(train_data, test_data, model, termLabels) { # 直接拼接公式字符串并解析,指定环境为全局 fixForm <- as.formula(paste("Y ~", paste(termLabels, collapse=" + ")), env = .GlobalEnv) fit <- nlme::lme(fixForm, data=train_data, random=~ 1|ID) train_pred <- predict(fit, newdata=train_data, level=0, na.action=na.exclude) rtrain <- cor.test(train_data$Y, train_pred) test_pred <- predict(fit, newdata=test_data, level=0, na.action=na.exclude) rtest <- cor.test(test_data$Y, test_pred) tmp <- data.frame(Model=model, R_train=rtrain$estimate, R_test=rtest$estimate) return(tmp) }
方法对比
- 方法1更稳妥:保留了公式的原始环境,适合包含复杂变量或局部对象的场景。
- 方法2更简洁:适合变量均存在于数据或全局环境的简单场景。
内容的提问来源于stack exchange,提问作者Jeff Phillips
相关产品推荐
相关产品推荐

