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

为何emmeans()需硬编码公式,无法从动态线性模型提取?

动态提取公式用于gls后emmeans报错的解决方案

问题场景

在处理含异方差的模型事后检验时,若从动态模型中提取公式传入gls(),再用emmeans()执行事后检验会触发报错;但硬编码公式则能正常运行。以下分Shiny和非Shiny场景给出最小可复现示例:

Shiny场景MRE

模拟大型应用中用户指定模型、ANOVA显著后执行事后检验的流程,需构建按效应组合设置不同方差的gls模型:

library(shiny)
library(nlme)
library(emmeans)

# 模拟数据
set.seed(123)
dat <- expand.grid(percent = factor(c("5%", "10%", "15%")),
                   cycle = factor(c("1", "2", "3")),
                   rep = 1:5)
dat$value <- rnorm(nrow(dat), 
                   mean = with(dat, as.numeric(percent) + as.numeric(cycle)),
                   sd = with(dat, as.numeric(percent)*0.5))

ui <- fluidPage(
  actionButton("run", "Run Post Hoc")
)

server <- function(input, output, session) {
  observeEvent(input$run, {
    # 模拟用户动态选择的线性模型
    lm_model <- lm(value ~ percent*cycle, data = dat)
    
    # 提取公式用于gls模型
    gls_formula <- formula(lm_model)
    
    # 构建带异方差的gls模型
    gls_model <- gls(gls_formula, 
                     data = dat,
                     weights = varIdent(form = ~1 | percent:cycle))
    
    # 动态公式传入emmeans(触发报错)
    results <- emmeans(gls_model, pairwise ~ percent*cycle)
    print(results)
    
    # 硬编码公式(正常运行)
    results2 <- emmeans(gls_model, pairwise ~ percent*cycle)
    print(results2)
  })
}

shinyApp(ui, server)

报错信息:Error in eval(call$model) : object 'gls_formula' not found

非Shiny场景MRE

library(nlme)
library(emmeans)

set.seed(123)
dat <- expand.grid(percent = factor(c("5%", "10%", "15%")),
                   cycle = factor(c("1", "2", "3")),
                   rep = 1:5)
dat$value <- rnorm(nrow(dat), 
                   mean = with(dat, as.numeric(percent) + as.numeric(cycle)),
                   sd = with(dat, as.numeric(percent)*0.5))

# 初始模型
lm_model <- lm(value ~ percent*cycle, data = dat)
gls_formula <- formula(lm_model)

# 构建gls模型
gls_model <- gls(gls_formula, 
                 data = dat,
                 weights = varIdent(form = ~1 | percent:cycle))

# 执行事后检验(触发报错)
results <- emmeans(gls_model, pairwise ~ percent*cycle)

报错信息:Error in call$model[[2]] : object of type 'symbol' is not subsettable

问题根源

gls()会保存调用时的符号引用而非实际公式表达式。当你传入gls_formula这个符号对象时,gls的调用记录里只保存了gls_formula这个名称,而非value ~ percent*cycle的实际公式。emmeans()在解析模型时会尝试评估这个符号,导致找不到对象或无法子集化符号,从而报错。

解决方法

两种方式都能让gls()保存实际的公式表达式,避免符号引用问题:

方法1:在gls调用中强制解析公式

用eval()直接解析公式对象,让gls记录实际的公式表达式:

# 替换原gls模型构建代码
gls_model <- gls(eval(gls_formula), 
                 data = dat,
                 weights = varIdent(form = ~1 | percent:cycle))

方法2:提取公式的原始表达式

直接从原模型中提取公式的左右部分,重新构建公式表达式:

# 提取公式的响应变量和预测变量部分
gls_formula_expr <- formula(lm_model)[[2]] ~ formula(lm_model)[[3]]

# 构建gls模型
gls_model <- gls(gls_formula_expr, 
                 data = dat,
                 weights = varIdent(form = ~1 | percent:cycle))

两种方法都能让emmeans()正确解析模型,顺利执行事后检验。


内容的提问来源于stack exchange,提问作者Steven Ouellette

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:15:54