相关性分析用来衡量变量之间线性关联强弱,是探索性数据分析、特征筛选最常用手段。本文讲解 Pandas 自带相关系数计算、可视化、显著性、多变量筛选、实战避坑,沿用销售明细示例。
前置导入
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 热力图需要 seaborn
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
一、基础示例数据
data = {
"数量": [2, 1, 5, 3, 4, 2, 6, 3],
"单价": [89, 45, 1200, 199, 299, 89, 1350, 199],
"金额": [178, 45, 6000, 597, 1196, 178, 8100, 597],
"运费": [10, 8, 20, 12, 15, 10, 22, 12],
"客户评分": [4.8, 4.5, 4.2, 4.7, 4.6, 4.8, 4.1, 4.7]
}
df = pd.DataFrame(data)
二、corr() 核心函数
df.corr() 计算相关系数矩阵,支持三种算法:
method="pearson":皮尔逊相关(默认,线性相关,要求正态分布)method="spearman":斯皮尔曼秩相关(单调相关,不受异常值影响,非正态优先)method="kendall":肯德尔tau系数,适合有序分类、小样本
# 皮尔逊相关系数
corr_pearson = df.corr(method="pearson")
print(corr_pearson)
# 斯皮尔曼秩相关
corr_spearman = df.corr(method="spearman")
print(corr_spearman)
相关系数解读
取值范围:[-1, 1]
- 1:完全正相关;-1:完全负相关;0:无线性相关
- 0.7 ~ 1:强正相关
- 0.3 ~ 0.7:中等相关
- 0 ~ 0.3:弱相关
⚠️ 重点:相关 ≠ 因果! 只是统计上共同变化,不能直接判定因果关系。
三、提取单个变量的相关关系
比如只看「金额」和其他变量的相关性:
corr_with_amount = corr_pearson["金额"].sort_values(ascending=False)
print(corr_with_amount)
四、热力图可视化(最常用)
plt.figure(figsize=(8, 6))
sns.heatmap(
corr_pearson,
annot=True, # 显示系数数值
cmap="coolwarm", # 配色:蓝负红正
vmin=-1, vmax=1,
fmt=".2f"
)
plt.title("皮尔逊相关系数热力图")
plt.tight_layout()
plt.show()
五、筛选高相关变量(特征筛选)
业务场景:多重共线性排查,剔除高度冗余特征
# 阈值,大于0.7判定为高度相关
threshold = 0.7
# 取出上三角矩阵(去掉对角线、去重)
upper = corr_pearson.where(np.triu(np.ones(corr_pearson.shape), k=1).astype(bool))
# 找出高相关列
high_corr_cols = [col for col in upper.columns if any(upper[col].abs() > threshold)]
print("高度相关字段:", high_corr_cols)
本例中:金额 = 数量 × 单价,天然和数量、单价强相关,属于典型多重共线性。
六、pandas 只算相关系数,没有P值(显著性)
corr() 只返回相关系数,不返回p值,无法判断是否统计显著。
如需p值,使用 scipy.stats:
from scipy.stats import pearsonr
# 计算 数量 和 金额 的相关系数 + p值
r, p_value = pearsonr(df["数量"], df["金额"])
print(f"相关系数 r={r:.3f}, p值={p_value:.4f}")
- p < 0.05:相关性统计显著
- p > 0.05:相关可能是随机波动
批量计算所有变量配对的p值封装:
def corr_pval(df):
cols = df.columns
n = len(cols)
p_matrix = pd.DataFrame(np.ones((n,n)), index=cols, columns=cols)
for i in range(n):
for j in range(i+1, n):
_, p = pearsonr(df[cols[i]], df[cols[j]])
p_matrix.iloc[i,j] = p
p_matrix.iloc[j,i] = p
return p_matrix
p_mat = corr_pval(df)
print(p_mat)
七、分类型变量怎么做相关性?
corr() 只能处理数值列,字符串分类不能直接计算。
两种方案:
- 独热编码(one-hot),再corr
df_dummy = pd.get_dummies(df["商品"], prefix="商品")
df_merge = pd.concat([df, df_dummy], axis=1)
- 卡方检验(分类vs分类),不再用corr
八、缺失值对corr的影响
corr() 默认 min_periods=1,计算时会自动成对删除缺失行(pairwise deletion)
# 自定义最少有效样本数,样本太少不计算
corr = df.corr(min_periods=5)
如果缺失分布不均匀,成对删除会导致每次相关系数样本不一样,结果容易失真。
大数据缺失多的时候,优先先做数据清洗,再做相关性。
九、实战流程模板(可直接复制)
def analysis_corr(df):
# 1. 只保留数值列
df_num = df.select_dtypes(include=[np.number])
# 2. 计算相关矩阵
corr_mat = df_num.corr(method="spearman")
# 3. 输出和目标字段相关性排序
target_corr = corr_mat["金额"].sort_values(ascending=False)
print(target_corr)
# 4. 热力图
plt.figure(figsize=(8,6))
sns.heatmap(corr_mat, annot=True, cmap="coolwarm", vmin=-1, vmax=1, fmt=".2f")
plt.title("Spearman 相关性热力图")
plt.show()
return corr_mat
corr_result = analysis_corr(df)
十、常见坑汇总
- 皮尔逊对异常值敏感,有极端值优先用 Spearman
- 非线性强相关,corr 会接近0(比如 y=x²),相关系数抓不到非线性关系
- 多重共线性:模型训练时,高相关特征不要一起丢进线性模型
- 不要用相关系数判断因果,经典例子:冰淇淋销量和溺水人数正相关(共同受温度影响)
- 分类文本不能直接丢进corr,必须编码
- 样本量太小的时候,相关系数波动很大,一定要看p值
十一、拓展方向
- 互信息(mutual_info):捕捉非线性关联,sklearn.feature_selection
- VIF方差膨胀因子:专门检测多重共线性
- 偏相关分析:控制其他变量后,看两个变量净相关
0 条笔记