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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 00:34:55