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

statsmodels中双向嵌套ANOVA结果与R不一致的问题排查

问题分析与解决

核心原因

statsmodels的公式语法与R存在关键差异,你使用的age/C(dose)没有正确实现嵌套ANOVA的模型结构,导致拟合的模型和R完全不一致,最终平方和结果无法匹配。

具体来说:

  • R中a / b等价于a + a:b,表示先拟合主效应a,再拟合a分组内b的嵌套效应;
  • 但statsmodels中age/C(dose)会解析为age + age:C(dose),这里的C(dose)是全局因子水平(D1/D2/D3/D4),而你的数据中age=1仅包含D1/D2、age=2仅包含D3/D4,这会产生多个无数据的交叉组合(如age1-D3、age2-D1等),statsmodels自动剔除这些无效项后,拟合的模型结构和R完全不同。

正确实现方式

要得到和R一致的嵌套ANOVA结果,需要让statsmodels拟合和R逻辑相同的模型,以下两种方法都可以:

方法1:创建复合嵌套因子

将age和dose组合成唯一的分组因子,明确表示每个age下的dose是独立的:

import pandas as pd
import numpy as np
import statsmodels.api as sm
from statsmodels.formula.api import ols

# 处理数据(已省略加载步骤)
df['age_dose'] = df['age'].astype(str) + '_' + df['dose']

# 拟合嵌套模型:age主效应 + 组内dose效应
mod = ols('expr ~ age + age_dose', data=df).fit()
anova_table = sm.stats.anova_lm(mod, typ=1)
print(anova_table)

方法2:直接指定有效交互项

如果不想创建新因子,可直接指定仅包含有效交叉组合的交互项(你的数据已满足age内dose水平唯一):

mod = ols('expr ~ age + age:C(dose)', data=df).fit()
anova_table = sm.stats.anova_lm(mod, typ=1)
print(anova_table)

验证总平方和

手动计算总平方和确认结果:

total_ss = np.sum((df['expr'] - df['expr'].mean())**2)
print(total_ss)  # 输出约1805.55,与R结果一致

使用上述正确模型后,ANOVA表中sum_sq列的总和(模型平方和+残差平方和)会与手动计算值匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 08:03:57