多重插补(mi)是基于数据分布生成多个带随机变异的完整数据集并按rubin规则汇总结果的方法;simpleimputer因单次插补低估不确定性,尤其在缺失>5%或非完全随机时失效。

什么是多重插补,为什么不能只用 SimpleImputer?
多重插补(Multiple Imputation, MI)不是“填一个数”,而是基于数据分布生成多个合理、带随机变异的完整数据集,再对每个数据集分别建模、汇总结果。它能正确反映缺失带来的不确定性——而 SimpleImputer 这类单次插补会低估标准误、扭曲置信区间,尤其在缺失比例 >5% 或缺失机制非完全随机(MNAR/MAR)时风险明显。
Python 中最成熟、符合统计规范的实现是 statsmodels 的 MICEData,它严格遵循 Rubin 的多重插补框架,支持自定义插补模型(如线性回归、逻辑回归、预测均值匹配),不是简单套用均值/中位数。
用 MICEData 做多重插补的三步实操
核心流程:初始化 → 迭代拟合 → 提取插补数据集。注意它默认只处理数值型变量,分类变量需先编码(如 pd.get_dummies 或 LabelEncoder),且不自动处理高基数类别特征。
- 确保数据无全空列:
df.dropna(axis=1, how='all'),否则MICEData会报ValueError: design matrix has zero variance - 初始化时指定
imp_model:对连续变量用sm.OLS,对二元变量用sm.Logit,并传入对应列名;例如:imp_model={'income': sm.OLS, 'is_employed': sm.Logit} - 调用
next_sample()至少 5 次(推荐 20–50 次)以达到收敛,每次调用返回一个完整数据集(pandas.DataFrame),不是“填充后的原 df”
from statsmodels.imputation.mice import MICEData import statsmodels.api as sm <p>mice_data = MICEData(df, perturbation_method='gaussian', k<em>pmm=5) for </em> in range(20): mice_data.update_all() imputed_dfs = [mice<em>data.data.copy() for </em> in range(5)] # 取 5 个独立插补集 </p>
插补后怎么合并分析结果?别跳过 pool 步骤
直接对 5 个插补数据集分别跑 sm.OLS(y ~ x) 得到 5 组系数和标准误,不能取平均——必须用 MICEData 自带的 pool 方法合并。它按 Rubin 规则计算总方差:total_var = within_var + (1 + 1/m) * between_var(m 是插补次数)。
- 每轮插补后立即拟合模型,把结果存进列表:
results = [model.fit() for model in models] - 用
mice_data.pool(results)返回一个PooledResults对象,其.summary()输出已校正的标准误和 p 值 - 若手动实现回归,漏掉
pool就等于白做多重插补——结果仍会显著高估统计效力
常见报错和绕过方案
MICEData 对输入敏感,几个高频卡点:
-
LinAlgError: Singular matrix:某列与其他列完全共线(如哑变量未删基准组),用np.linalg.matrix_rank(X)检查设计矩阵秩,或加drop_first=True在get_dummies -
ConvergenceWarning: Maximum number of iterations reached:默认迭代 10 次不够,显式设max_iter=50并检查mice_data.converged - 分类变量插补后出现非法类别(如 -1 或 2.3):说明用了
OLS插补分类列,必须改用Logit或Probit,并在拟合前确保目标列是 0/1 整数型
多重插补真正的复杂点不在代码行数,而在理解“插补是建模过程的一部分”——你得为每个含缺失的变量指定一个合理的插补模型,而不是依赖黑盒。这要求你对变量间关系有基本判断,比如知道 income 和 education_years 相关,才该把后者放进 income 的插补公式里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











