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

如何在Statsmodels逻辑回归中获取实际预测边际而非dy/dx?

如何在Statsmodels中计算Logit模型的预测边际(类似Stata margin)

问题场景

你使用smf.logit拟合了如下逻辑回归模型:

model_5a_1 = smf.logit('''fluid ~ C(examq3_n, Treatment(reference = 2.0)) + C(pmhq3_n) + C(fluidq3_n) + C(mapq3_n, Treatment(reference = 3.0)) + 
                  C(examq6_n, Treatment(reference = 2.0)) + C(pmhq6_n) + C(fluidq6_n) + C(mapq6_n, Treatment(reference = 3.0)) +
                  + C(case, Treatment(reference = 2))''',
                 data = case1_2_vars).fit()
print(model_5a_1.summary())

尝试用get_margeff()得到的是dy/dx形式的边际效应,但你需要的是预测边际(即给定自变量取值时的平均预测概率),类似Stata的margin命令;使用get_prediction()时又出现PatsyError: categorical data cannot be >1-dimensional错误。

解决方案

要实现类似Stata margin的预测边际计算,核心是先构造符合要求的参考数据集,再用模型计算预测概率,具体步骤如下:

1. 构造参考数据集

创建一个数据集,将目标分类变量遍历所有水平,其他变量固定在均值(或你需要的参考值,比如中位数):

import pandas as pd

# 获取模型用到的自变量列表
var_names = model_5a_1.model.exog_names
# 生成基础数据:非分类变量取均值,分类变量先保留一个基准水平
base_data = case1_2_vars[var_names].mean().to_frame().T

# 定义所有分类变量
categorical_vars = ['examq3_n', 'pmhq3_n', 'fluidq3_n', 'mapq3_n', 'examq6_n', 'pmhq6_n', 'fluidq6_n', 'mapq6_n', 'case']

# 生成包含所有分类水平组合的边际数据集
margins_data = pd.DataFrame()
for var in categorical_vars:
    # 获取当前变量的所有唯一取值
    levels = case1_2_vars[var].unique()
    # 复制基础数据并替换当前变量的取值
    temp_data = pd.concat([base_data]*len(levels), ignore_index=True)
    temp_data[var] = levels
    margins_data = pd.concat([margins_data, temp_data], ignore_index=True)

# 去重避免重复组合
margins_data = margins_data.drop_duplicates().reset_index(drop=True)

2. 计算预测边际概率

用构造好的数据集调用get_prediction(),即可得到带置信区间的预测边际:

# 计算预测结果及置信区间
predictions = model_5a_1.get_prediction(margins_data)
pred_summary = predictions.summary_frame()

# 合并变量取值与预测结果
final_result = pd.concat([margins_data, pred_summary[['mean', 'mean_ci_lower', 'mean_ci_upper']]], axis=1)

# 示例:按case变量分组展示预测边际
print(final_result.groupby('case')[['mean', 'mean_ci_lower', 'mean_ci_upper']].first())

3. 简化版:针对单个变量计算边际

如果只需要计算某一个分类变量的预测边际,可以用自定义函数简化:

def get_single_var_margins(model, var_name, data):
    levels = data[var_name].unique()
    base_data = data.drop(var_name, axis=1).mean().to_frame().T
    result_list = []
    
    for level in levels:
        temp_data = base_data.copy()
        temp_data[var_name] = level
        pred = model.get_prediction(temp_data).summary_frame()
        result_list.append({
            var_name: level,
            'pred_prob': pred['mean'].iloc[0],
            'lower_ci': pred['mean_ci_lower'].iloc[0],
            'upper_ci': pred['mean_ci_upper'].iloc[0]
        })
    return pd.DataFrame(result_list)

# 计算case变量的预测边际
case_margins = get_single_var_margins(model_5a_1, 'case', case1_2_vars)
print(case_margins)

错误原因说明

之前调用get_prediction()报错,是因为直接传入的原数据或格式错误的数据集,包含多维分类变量结构,Patsy无法正确解析;而构造的参考数据集是单条基准记录复制替换分类水平,格式符合模型的输入要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:38:01