Spearman秩相关系数用scipy.stats.spearmanr计算,传入两个一维数组得(rho, p_value),rho即系数;需预处理缺失值和分类变量,批量计算推荐df.corr(method="spearman")["target"].sort_values(key=abs, ascending=False)。

怎么用 spearmanr 计算单对特征的秩相关性
Scikit-learn 本身不提供 spearmanr —— 它是 scipy.stats 的函数。很多人在 sklearn.feature_selection 里翻半天没找到,是因为选错了模块。
用 spearmanr 的核心逻辑是:它不依赖线性假设,适合处理单调但非线性的关系(比如“收入越高,房价越高”,哪怕不是直线上升),也对异常值更鲁棒。
- 必须传入两个一维数组,
spearmanr(x, y)返回元组(rho, p_value),只取第一个值rho就是 Spearman 相关系数 -
x和y不能含缺失值,否则报错ValueError: Input arrays must not contain NaNs,得提前用dropna()或np.nan_to_num() - 分类变量要先编码(如
LabelEncoder或pd.Categorical),否则秩序无意义
from scipy.stats import spearmanr
rho, _ = spearmanr(train_housing["median_income"], train_housing["median_house_value"])
print(f"Spearman rho: {rho:.3f}") # 比如输出 0.687怎么批量计算所有特征对目标变量的 Spearman 相关性
想一次性看全部特征和 median_house_value 的 Spearman 关系?别手写循环——Pandas 的 apply 配合 spearmanr 更稳。
注意:Pandas 内置的 .corr(method="spearman") 确实能算,但它底层调的是 scipy,且会自动跳过 NaN、做排序秩转换,行为一致,但返回的是完整相关矩阵,而你往往只关心目标列。
- 直接用
df.corr(method="spearman")["median_house_value"].sort_values(key=abs, ascending=False)最省事 - 如果数据量大(>10 万样本),
spearmanr会变慢,因为要排序;此时可考虑采样(如df.sample(10000))再算 - 结果中出现
NaN,大概率是某特征全为同一值(方差为 0),秩无法定义,得先用VarianceThreshold过滤掉
为什么不用 SelectKBest + spearmanr 直接筛选?
因为 sklearn.feature_selection.SelectKBest 不支持 spearmanr 作为 score_func——它只认接受 (X, y) 并返回一维数组的函数,而 spearmanr 是双输入标量输出,类型不匹配。
强行包装会出错:TypeError: spearmanr() missing 1 required positional argument: 'y'。有人试过用 lambda 匿名函数绕过,但会导致无法 pickle(影响 Pipeline)、且评分向量维度错乱。
- 正确做法:先用
df.corr(method="spearman")得到各特征得分,再用SelectFromModel或手动索引选取 top-k - 若坚持走 sklearn 流水线,可用
mutual_info_regression替代——它不要求单调性,还能捕获非线性依赖,且原生支持SelectKBest - 别把 Spearman 当万能药:它只测单调性,对 U 型、周期型关系完全不敏感(比如“温度→用电量”可能是倒 U 型)
和 Pearson 相关性对比时最容易忽略的三点
很多人默认“Spearman 更好”,其实要看场景。两者差异不在“谁高级”,而在“谁适配当前数据形态”。
- Pearson 对离群点极度敏感;Spearman 把值转成秩,天然抗噪——但代价是丢掉原始尺度信息,比如两个特征差 10 倍和差 100 倍,在秩上没区别
- 当特征分布严重偏态(如收入、房价),Pearson 可能低估真实关联,Spearman 更可靠;但若已做过对数变换,Pearson 往往更稳定
- Scikit-learn 中的
RFECV、PermutationImportance等后续步骤,底层默认用模型预测误差,和相关性方法无关——别指望靠换 Spearman 就让 RFE 结果变好
真正卡住人的,往往不是不会调函数,而是没意识到 Spearman 给出的只是一个单调性快照,它不回答“这个特征要不要进模型”,只回答“它和目标有没有一致增减趋势”。后面还得结合业务、可解释性、模型类型一起判断。

















