卡方检验适用于分类变量间的独立性检验与分布差异分析,核心用于两组或多组定性数据比较、特征选择中类别型特征与类别型目标变量的关联性评估,不适用于连续型数据或回归任务。

卡方检验适用于什么场景?
卡方检验(chi2)在特征选择中只适用于类别型特征 + 类别型目标变量的组合。它衡量的是两个分类变量之间的独立性:如果 chi2 统计量越大、p 值越小,说明该特征与目标变量的关联性越强。
常见错误是直接对数值型特征(如年龄、收入)或目标为回归任务(如房价预测)使用 chi2 —— 这会导致 ValueError: Input X must be non-negative 或结果无意义。必须先确保:
- 所有特征列已做
LabelEncoder或OneHotEncoder转为非负整数(不能是字符串或浮点数) - 目标变量
y是一维整数标签(如 0/1 或 0/1/2),不是 one-hot 编码后的二维数组 - 数据中不能有缺失值(
NaN),否则chi2会报错
如何用 SelectKBest + chi2 做特征筛选?
核心是组合使用 sklearn.feature_selection.SelectKBest 和 sklearn.feature_selection.chi2。注意两点关键限制:
-
chi2要求输入 X 全为**非负数**,所以必须先做编码(OrdinalEncoder或OneHotEncoder),不能直接传入原始字符串列 -
SelectKBest默认按统计量排序选前 K 个,但不会返回 p 值;如需查看每个特征的 p 值,得手动调用chi2(X, y)
示例流程:
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.preprocessing import OrdinalEncoder
import numpy as np
<h1>假设 X_cat 是纯类别列组成的 DataFrame(如 ['gender', 'city', 'edu'])</h1><p>enc = OrdinalEncoder(dtype=np.int64)
X_encoded = enc.fit_transform(X_cat).astype(int)</p><h1>注意:y 必须是一维整数数组,如 [0, 1, 1, 0, ...]</h1><p>selector = SelectKBest(score_func=chi2, k=3)
X_selected = selector.fit_transform(X_encoded, y)</p><h1>查看被选中的列名</h1><p>selected_mask = selector.get_support()
print("Selected features:", X_cat.columns[selected_mask].tolist())</p>
为什么 chi2 有时返回全零或报错?
最常踩的坑是数据格式不合规:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 特征含负数(比如用
LabelEncoder后没重映射,某些类别被编成 -1)→chi2报ValueError: Input X must be non-negative - 某类别特征在训练集中出现频率极低(如某城市只出现 1 次),导致卡方期望频数
- 目标变量类别分布极度倾斜(如 99% 是 0 类),
chi2仍能算,但低频类别的关联容易被掩盖
解决办法:
- 统一用
OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1)后,再把 -1 替换为 0 或最大值+1,保证非负 - 对低频类别做合并(如“其他”)、或直接过滤掉出现次数 chi2
- 搭配
mutual_info_classif对照验证——它不要求非负,对稀疏和偏态更鲁棒
和 mutual_info_classif 比,chi2 有什么实际差异?
chi2 是基于频数表的精确统计检验,而 mutual_info_classif 是基于信息熵的估计量。实际影响很具体:
-
chi2对样本量敏感:小数据集下 p 值波动大,可能把偶然相关的特征排很高 -
mutual_info_classif支持浮点型输入(内部自动离散化),可跳过编码步骤;但需要设random_state才能复现结果 - 当某个特征和目标存在强非线性关系(如“城市=北京”和“是否高薪”高度相关,但其他城市都弱),
chi2更敏感;而mutual_info_classif在离散化粒度不合适时会漏判
真正上线前,别只信一个指标。至少对比两者的 top-5 特征交集,再人工检查业务合理性——比如“用户等级”和“是否续费”的卡方 p 值很小,但若等级本身由续费行为反推生成,就是泄漏,得删。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










