mcpField
S
statsmodels

statsmodels

github.com/tondevrel数据与数据库2583 次安装39 周前更新
代码仓库

关于 statsmodels

statsmodels 是面向分析人员和研究者的 Python 统计建模与推断库,提供可解释的估计、检验和诊断。它通过公式与数组接口支持回归、时间序列等统计方法。

主要功能

  1. 01公式与数组建模接口
  2. 02线性及广义线性模型
  3. 03时间序列与生存分析
  4. 04假设检验和模型诊断
  5. 05详细统计摘要

适用场景

  1. 01估计回归效应及置信区间
  2. 02使用 ANOVA 检验组间差异
  3. 03建模和检验时间序列数据
  4. 04分析处理效应或生存结果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tondevrel/scientific-agent-skills --skill statsmodels

安装后在 Claude Code 中输入/statsmodels确认已加载。

详细介绍

Statsmodels - 统计建模与推断

Statsmodels 是 Python 与 R 风格严谨统计分析之间的桥梁。它允许用户使用公式(通过 patsy)估计模型、执行广泛的诊断检验,并生成学术出版领域的标准详细摘要表。

适用场景

  • 估计具有详细诊断的线性回归模型(OLS、WLS)。
  • 广义线性模型(GLM):Logistic、Poisson、Gamma 回归。
  • 时间序列分析(ARIMA、SARIMAX、VAR、状态空间模型)。
  • 统计假设检验(t 检验、ANOVA、正态性、异方差性)。
  • 生存分析(Kaplan-Meier、Cox 比例风险)。
  • 估计处理效应并进行因果推断。
  • 非参数统计(核密度估计)。

参考文档

官方文档:https://www.statsmodels.org/stable/
公式 API:https://www.statsmodels.org/stable/example_formulas.html
搜索模式:sm.OLS、smf.ols、sm.tsa、results.summary()、statsmodels.api

核心原则

Statsmodels 与 scikit-learn 的区别
特性scikit-learnStatsmodels
目标预测(准确性)推断(解释/p 值)
接口fit / predictfit / summary
预处理Pipeline 对象公式(Patsy)或设计矩阵
诊断交叉验证残差分析、p 值、CI
两种 API
  • API(statsmodels.api):需要显式添加常数项(截距),并使用类似 NumPy 的数组。
  • 公式 API(statsmodels.formula.api):使用 R 风格公式(y ~ x1 + x2),并可直接处理 Pandas DataFrame。(推荐大多数用户使用。)

快速参考

安装
pip install statsmodels patsy
标准导入
import statsmodels.api as sm
import statsmodels.formula.api as smf
import pandas as pd
import numpy as np
基本模式 - 普通最小二乘法(OLS)
import statsmodels.formula.api as smf

# 1. Define model with R-style formula
# 'y ~ x1 + x2' means: y = beta0 + beta1*x1 + beta2*x2
model = smf.ols('tip ~ total_bill + size', data=df_tips)

# 2. Fit the model
results = model.fit()

# 3. Print the comprehensive results table
print(results.summary())

# 4. Access specific values
p_values = results.pvalues
params = results.params # beta coefficients

关键规则

✅ 应该做
  • 检查残差 - 始终绘制并检验残差(results.resid)的正态性和同方差性。
  • 添加常数项 - 如果使用 sm.api(而非公式),请记得执行 X = sm.add_constant(X),否则模型会经过原点(beta0 = 0)。
  • 使用分类变量 - 在公式中使用 C() 运算符(例如 y ~ C(region))自动创建虚拟变量。
  • 指定协方差类型 - 如果怀疑存在非恒定方差(异方差性),请使用 cov_type='HC3' 或 'cluster'。
  • 谨慎解读 R-squared - 如果残差呈现模式,即使 R-squared 很高,也不代表模型良好。
  • 检查多重共线性 - 使用 VIF(方差膨胀因子)确保预测变量之间没有高度相关。
❌ 不要做
  • 将预测等同于推断 - 模型的 R-squared 很高,并不意味着其系数代表现实世界中的因果效应。
  • 忽略截距 - 大多数物理和社会过程都需要常数项。
  • 使用过多预测变量导致过拟合 - 使用 AIC/BIC 指标对复杂模型进行惩罚。
  • 超出数据范围进行外推 - 统计模型仅在训练数据的适用范围内有效。

反模式(绝对不要)

import statsmodels.api as sm

# ❌ BAD: Forgetting the intercept in Array API
model = sm.OLS(y, X) # This forces the line through (0,0)
results = model.fit()

# ✅ GOOD: Add the constant
X = sm.add_constant(X)
model = sm.OLS(y, X).fit()

# ❌ BAD: Ignoring categorical data strings
# smf.ols('price ~ color', data=df) # Might fail if 'color' isn't numeric

# ✅ GOOD: Explicitly tell Statsmodels it's categorical
smf.ols('price ~ C(color)', data=df).fit()

# ❌ BAD: Only looking at R-squared
# print(results.rsquared) # Tells only part of the story

# ✅ GOOD: Inspecting the whole summary
print(results.summary()) # Check p-values, F-stat, Jarque-Bera

回归分析

线性模型(OLS、WLS)
# Multiple Linear Regression with interactions
# 'x1 * x2' includes x1, x2, and the interaction term x1:x2
model = smf.ols('y ~ x1 * x2 + np.log(x3)', data=df).fit()

# Weighted Least Squares (for heteroscedastic data)
wls_model = sm.WLS(y, X, weights=1.0/variance_estimates).fit()
广义线性模型(GLM)
# Logistic Regression (Binary outcome)
logit_model = smf.logit('admit ~ gre + gpa + C(rank)', data=df).fit()

# Poisson Regression (Count data)
poisson_model = smf.poisson('num_awards ~ math + C(prog)', data=df).fit()

# Negative Binomial (For over-dispersed counts)
nb_model = smf.glm('y ~ x1', data=df, family=sm.families.NegativeBinomial()).fit()

时间序列分析(tsa)

平稳性与建模
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.statespace.sarimax import SARIMAX

# 1. Test for Stationarity (Augmented Dickey-Fuller)
adf_result = adfuller(df['sales'])
print(f"ADF P-value: {adf_result[1]}") # p < 0.05 means stationary

# 2. SARIMAX (Seasonal ARIMA with eXogenous variables)
model = SARIMAX(df['sales'], 
                order=(1, 1, 1), 
                seasonal_order=(1, 1, 0, 12),
                exog=df['advertising'])
results = model.fit()

# 3. Forecasting
forecast = results.get_forecast(steps=12)
conf_int = forecast.conf_int()

ANOVA 与假设检验

from statsmodels.stats.anova import anova_lm

# Perform ANOVA on OLS model
model = smf.ols('yield ~ C(fertilizer) + C(soil)', data=df).fit()
anova_table = anova_lm(model, typ=2)

# Post-hoc tests (Tukey's HSD)
from statsmodels.stats.multicomp import pairwise_tukeyhsd
tukey = pairwise_tukeyhsd(endog=df['yield'], groups=df['fertilizer'], alpha=0.05)
print(tukey)

模型诊断

残差分析
import statsmodels.stats.api as sms

# 1. Test for Heteroscedasticity (Breusch-Pagan)
name = ['Lagrange multiplier statistic', 'p-value', 'f-value', 'f p-value']
test = sms.het_breuschpagan(results.resid, results.model.exog)
print(dict(zip(name, test)))

# 2. Test for Normality (Omnibus)
# Included in results.summary() by default. 

# 3. Check for Outliers (Influence)
influence = results.get_influence()
cooks_d = influence.cook_distance[0]

实用工作流

1. 稳健的科学报告流程
def analyze_experiment(df):
    """Rigorous analysis of an experimental dataset."""
    # 1. Fit model
    model = smf.ols('outcome ~ treatment + age + gender', data=df).fit()
    
    # 2. Diagnostic Plots (requires matplotlib)
    import matplotlib.pyplot as plt
    sm.graphics.plot_regress_exog(model, 'treatment')
    
    # 3. Check for Multicollinearity
    from statsmodels.stats.outliers_influence import variance_inflation_factor
    # (calculation for VIF...)
    
    return model.summary()
2. 市场组合建模(归因)
def estimate_attribution(df):
    # Log-log model to calculate elasticities
    # Coefficients will be % change in sales for 1% change in spend
    model = smf.ols('np.log(sales) ~ np.log(tv_spend) + np.log(digital_spend)', data=df).fit()
    return model.params
3. 生存分析
from statsmodels.duration.hazard_regression import PHReg

# Cox Proportional Hazards Model
model = PHReg.from_formula('time ~ age + C(treatment)', data=df, status=df['event'])
results = model.fit()
print(results.summary())

性能优化

使用 numba 计算似然

Statsmodels 主要使用 Python 和 Cython 编写,但一些较新的时间序列模块会使用经过优化的数值后端,以更快地拟合状态空间模型。

公式与设计矩阵

对于非常大的数据集(100 万行以上),使用 patsy 创建设计矩阵可能会大量消耗内存。在这种情况下,请手动构造 X 矩阵,并使用 sm.OLS(y, X)。

常见问题与解决方案

奇异矩阵错误

“LinAlgError: Singular matrix” 表示预测变量之间存在完全相关性(例如,同时包含 temp_celsius 和 temp_fahrenheit)。

# ✅ Solution: Remove redundant columns
df = df.drop('redundant_col', axis=1)
分类变量泄漏(虚拟变量陷阱)

同时包含截距项和所有类别的虚拟变量会导致完全多重共线性。

# ❌ Problem: y ~ dummy_cat1 + dummy_cat2 + dummy_cat3 + intercept 
# ✅ Solution: Statsmodels/Patsy automatically drops one category (ref category)
# to avoid this. Don't try to force all dummies in!
非平稳时间序列

预测非平稳序列会导致“伪回归”。

# ✅ Solution: Difference your data first
df['diff_y'] = df['y'].diff()
# Or use ARIMA with integrated term (d=1)

Statsmodels 是 Python 生态系统中统计有效性的黄金标准。它超越了黑盒预测,提供了高风险科学和经济决策所需的透明度与数学严谨性。

评论

支持 Markdown