DHARMa::simulateResiduals报错:UseMethod("mutate")无适用方法排查
问题:glmmTMB模型选择后DHARMa残差模拟报错成因
我使用glmmTMB包对数据集data拟合了零膨胀广义泊松模型,代码如下:
library(glmmTMB) library(dplyr) library(DHARMa) ml <- glmmTMB(menthlth ~ sex + medcost + ..., ziformula = ~ sex + medcost + X_educag + internet + ..., data = data %>% mutate(across(c(where(is.numeric), -menthlth), scale)), family = "genpois", control = glmmTMBControl(optCtrl = list(iter.max = 1e3, eval.max = 1e3))) model <- step(ml, direction = "both", k = log(nrow(data))) DHARMa::simulateResiduals(fittedModel = model, plot = T)
通过step()函数进行双向模型选择得到model对象后,调用DHARMa::simulateResiduals()时出现如下错误:
Error in UseMethod("mutate") : no applicable method for 'mutate' applied to an object of class "function" 17. mutate(., across(c(where(is.numeric), -menthlth), scale)) 16. data %>% mutate(across(c(where(is.numeric), -menthlth), scale)) 15. is.data.frame(data) 14. model.frame.default(drop.unused.levels = TRUE, formula = ~sex + medcost + X_educag + smoke100 + status + sleptim1 + exeroft1 + maxdrnks, data = data %>% mutate(across(c(where(is.numeric), -menthlth), scale))) 13. model.frame(drop.unused.levels = TRUE, formula = ~sex + medcost + X_educag + smoke100 + status + sleptim1 + exeroft1 + maxdrnks, data = data %>% mutate(across(c(where(is.numeric), -menthlth), scale))) 12. eval(mf, envir = environment(fixedform)) 11. eval(mf, envir = environment(fixedform)) 10. terms(eval(mf, envir = environment(fixedform))) 9. getXReTrms(formula, mf, fr = augFr, type = "conditional", contrasts = contrasts, sparse = sparseX[["cond"]], old_smooths = old_smooths$cond) 8. mkTMBStruc(RHSForm(omi$allForm$formula, as.form = TRUE), omi$allForm$ziformula, omi$allForm$dispformula, omi$allForm$combForm, mf, fr = augFr, yobs = yobs, respCol = respCol, weights = c(model.weights(augFr)), contrasts = omi$contrasts, family = omi$family, ziPredictCode = ziPredNm, ... 7. eval(expr, p) 6. eval.parent(mkTMBStruc(RHSForm(omi$allForm$formula, as.form = TRUE), omi$allForm$ziformula, omi$allForm$dispformula, omi$allForm$combForm, mf, fr = augFr, yobs = yobs, respCol = respCol, weights = c(model.weights(augFr)), contrasts = omi$contrasts, family = omi$family, ziPredictCode = ziPredNm, ... 5. predict.glmmTMB(object, type = "response", re.form = ~0) 4. predict(object, type = "response", re.form = ~0) 3. getFitted.default(fittedModel) 2. getFitted(fittedModel) 1. DHARMa::simulateResiduals(fittedModel = model, plot = T)
错误溯源指向数据预处理时的mutate语句,但模型拟合过程未出现该问题,请问该错误的成因是什么?
错误成因分析
- 动态数据表达式未持久化:拟合初始模型
ml时,你在data参数中直接使用了data %>% mutate(...)的管道操作,这种动态生成的数据集并未保存为独立对象。glmmTMB初始拟合时会即时执行管道生成数据,但step()返回的模型对象会保留这个原始的data参数表达式,而非预处理后的实际数据。当DHARMa调用predict()(进而触发model.frame())时,需要重新评估该表达式,若此时环境中data对象的类型发生变化(比如被误赋值为函数),就会导致mutate()无法作用于非数据框对象,触发报错。 - 模型环境的保留机制:
step()函数会保留原模型的调用环境。如果原模型的data参数是动态表达式而非静态数据框,后续调用模型相关函数时会重新执行该表达式。若此时dplyr的上下文丢失,或data名称出现冲突,就会引发mutate的方法匹配错误。
解决办法
1. 提前预处理并保存数据
避免在glmmTMB的data参数中直接写管道,先将预处理后的数据保存为独立对象,再传入模型:
# 提前完成数据缩放预处理 data_scaled <- data %>% mutate(across(c(where(is.numeric), -menthlth), scale)) # 使用预处理后的数据集拟合模型 ml <- glmmTMB(menthlth ~ sex + medcost + ..., ziformula = ~ sex + medcost + X_educag + internet + ..., data = data_scaled, family = "genpois", control = glmmTMBControl(optCtrl = list(iter.max = 1e3, eval.max = 1e3))) model <- step(ml, direction = "both", k = log(nrow(data_scaled))) DHARMa::simulateResiduals(fittedModel = model, plot = T)
2. 检查环境中的名称冲突
确认工作环境中未将data这个名称赋值给非数据框对象(比如误定义了data <- function(...)),若有冲突,及时清理或重命名该对象。
内容的提问来源于stack exchange,提问作者Paw in Data
相关产品推荐
相关产品推荐

