自学教程 学编程从这里开始

Pandas 相关性分析

相关性分析用来衡量变量之间线性关联强弱,是探索性数据分析、特征筛选最常用手段。本文讲解 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() 只能处理数值列,字符串分类不能直接计算。
两种方案:

  1. 独热编码(one-hot),再corr
df_dummy = pd.get_dummies(df["商品"], prefix="商品")
df_merge = pd.concat([df, df_dummy], axis=1)
  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)

十、常见坑汇总

  1. 皮尔逊对异常值敏感,有极端值优先用 Spearman
  2. 非线性强相关,corr 会接近0(比如 y=x²),相关系数抓不到非线性关系
  3. 多重共线性:模型训练时,高相关特征不要一起丢进线性模型
  4. 不要用相关系数判断因果,经典例子:冰淇淋销量和溺水人数正相关(共同受温度影响)
  5. 分类文本不能直接丢进corr,必须编码
  6. 样本量太小的时候,相关系数波动很大,一定要看p值

十一、拓展方向

  • 互信息(mutual_info):捕捉非线性关联,sklearn.feature_selection
  • VIF方差膨胀因子:专门检测多重共线性
  • 偏相关分析:控制其他变量后,看两个变量净相关
标签:

0 条笔记