Python探索性数据分析(EDA)怎么做?关键统计指标与分布检查

Chloe
Chloe
发布时间:2026-10-20 | 3人浏览过
原创

假设你刚从业务系统中导出一份含有数十万条记录的用户交易日志 CSV 文件,如果直接把这批数据丢给回归或分类模型,很可能会遭遇训练发散、预测失真或模型对极值极其敏感的问题。探索性数据分析(Exploratory Data Analysis,简称 EDA)的核心目的,就是通过系统的描述性统计指标与图形化分布检查,在建模前彻底摸清数据的集中趋势、离散范围、偏斜形态以及潜在的异常干扰,从而为后续的数据清洗、特征转换与算法选择提供可靠的客观依据。

Python探索性数据分析(EDA)怎么做?关键统计指标与分布检查
图 1:Python 探索性数据分析(EDA)的标准实施路径与分析递进流程

一、准备工作:搭建分析环境与数据初检

进行数据探索分析时,Python 生态中最基础且高效的依赖库包含 pandas、numpy、scipy 以及可视化库 matplotlib 与 seaborn。推荐在标准的 Python 3.9+ 虚拟环境中安装这些工具:

pip install pandas numpy scipy matplotlib seaborn

拿到数据集后的第一步是执行宏观结构检查,查验数据行列数、各列字段的数据类型以及缺失值覆盖率,避免在非数值型字段上强行执行统计运算。

import pandas as pd
import numpy as np

# 模拟构建一个具有实际特征的电商用户交易样本数据集
np.random.seed(42)
n_samples = 1000

data = {
    "user_id": np.arange(1001, 1001 + n_samples),
    # 右偏长尾分布:大部分订单金额在 50~200 之间,少数大客单价超 2000
    "order_amount": np.round(np.random.exponential(scale=120, size=n_samples) + 20, 2),
    # 近似正态分布:用户活跃天数
    "active_days": np.clip(np.round(np.random.normal(loc=45, scale=12, size=n_samples)), 1, 90),
    # 含有离群值的转化率得分
    "score": np.random.uniform(10, 95, size=n_samples)
}

df = pd.DataFrame(data)

# 基础结构探查
print("数据集形状 (行, 列):", df.shape)
print("\n缺失值统计:\n", df.isna().sum())
print("\n数据类型概览:\n", df.dtypes)
终端输出结果示例
数据集形状 (行, 列): (1000, 4) 缺失值统计: user_id 0 order_amount 0 active_days 0 score 0 dtype: int64 数据类型概览: user_id int64 order_amount float64 active_days float64 score float64 dtype: object

二、核心统计指标体系与数学解读

单一统计值往往具有很强的欺骗性。例如,仅仅观察一组薪资数据的均值,往往会因为几位超高收入者而严重高估普遍水平。因此,必须将集中趋势、离散程度与形态指标(偏度、峰度)结合起来,形成完整的数值坐标系。

Python探索性数据分析(EDA)怎么做?关键统计指标与分布检查
图 2:连续数值特征探索的核心度量维度与参数含义

1. 关键指标的 Python 计算实操

利用 Pandas 和 SciPy,我们可以一次性输出全面的描述统计量,并编写自动化函数提取五数概括(最小值、下四分位数、中位数、上四分位数、最大值)以及偏度、峰度指标:

from scipy import stats

def calculate_distribution_metrics(series: pd.Series) -> pd.Series:
    """计算指定数值列的关键位置与形态统计指标"""
    q1 = series.quantile(0.25)
    q3 = series.quantile(0.75)
    iqr = q3 - q1
    
    metrics = {
        "样本总量": series.count(),
        "均值 (Mean)": series.mean(),
        "中位数 (Median)": series.median(),
        "标准差 (Std)": series.std(),
        "四分位距 (IQR)": iqr,
        "偏度 (Skewness)": series.skew(),
        "峰度 (Kurtosis)": series.kurtosis()  # pandas 默认计算 Fisher 超额峰度(正态分布为 0)
    }
    return pd.Series(metrics)

# 对比两组具有不同分布特征的变量
metrics_summary = pd.DataFrame({
    "订单金额 (order_amount)": calculate_distribution_metrics(df["order_amount"]),
    "活跃天数 (active_days)": calculate_distribution_metrics(df["active_days"])
})

print(metrics_summary.round(3))
终端输出结果示例
订单金额 (order_amount) 活跃天数 (active_days) 样本总量 1000.000 1000.000 均值 (Mean) 138.452 44.821 中位数 (Median) 101.340 45.000 标准差 (Std) 116.891 11.754 四分位距 (IQR) 131.220 16.000 偏度 (Skewness) 1.984 0.038 峰度 (Kurtosis) 4.812 -0.124
指标解读对比要点
从输出可以看出:active_days 的均值(44.821)与中位数(45.000)高度重合,偏度为 0.038(非常接近 0),峰度为 -0.124,表现出极其标准的对称正态特征;而 order_amount 的均值(138.452)显著高于中位数(101.340),偏度达到 1.984,峰度达到 4.812,属于典型的强右偏且厚尾分布,存在长尾极端大额订单。

三、分布检查工具的对比与图形化实现

统计数字能给出量化轮廓,但无法完全还原细节。例如,当数据存在双峰(Bimodal)现象时,均值与中位数可能恰好落入两峰之间的波谷,仅看数字就会遗漏重要业务分群。因此必须结合分布图形进行校验。

Python探索性数据分析(EDA)怎么做?关键统计指标与分布检查
图 3:四类主流分布检查工具的应用场景与诊断特性对比

2. 使用 Python 绘制分布检查组合图

在实际工程中,通常通过 matplotlib 和 seaborn 构建 2x2 的子图矩阵,将直方图+KDE、箱线图、Q-Q 图与 ECDF 放在同一画布中,全面排查目标特征:

import matplotlib.pyplot as plt
import seaborn as sns

def plot_distribution_diagnostics(series: pd.Series, feature_name: str):
    fig, axes = plt.subplots(2, 2, figsize=(12, 10))
    plt.subplots_adjust(hspace=0.3, wspace=0.25)
    
    # 1. 直方图 + KDE 曲线
    sns.histplot(series, kde=True, ax=axes[0, 0], color="#0f4c81", bins=30)
    axes[0, 0].set_title(f"{feature_name} - 直方图与核密度估计")
    axes[0, 0].set_ylabel("频数")
    
    # 2. 箱线图 (识别 1.5*IQR 离群点)
    sns.boxplot(x=series, ax=axes[0, 1], color="#77B9AE")
    axes[0, 1].set_title(f"{feature_name} - 箱线图")
    
    # 3. Q-Q 图 (检验正态性契合)
    stats.probplot(series, dist="norm", plot=axes[1, 0])
    axes[1, 0].set_title(f"{feature_name} - 正态 Q-Q 图")
    axes[1, 0].get_lines()[0].set_color("#0f4c81")
    axes[1, 0].get_lines()[1].set_color("#e11d48")  # 理论基准线标红
    
    # 4. ECDF 经验累积分布
    sns.ecdfplot(series, ax=axes[1, 1], color="#0f766e")
    axes[1, 1].set_title(f"{feature_name} - 经验累积分布 (ECDF)")
    axes[1, 1].set_ylabel("累计概率")
    axes[1, 1].grid(True, linestyle="--", alpha=0.5)

    plt.tight_layout()
    plt.show()

# 执行诊断绘图
plot_distribution_diagnostics(df["order_amount"], "订单金额")

四、统计假设检验:量化验证正态性

虽然图形能够给出明确的视觉倾向,但在许多科学分析或受到合规审计的业务中,我们需要用可量化的统计假设检验给出确定性结论。常用的正态性检验包括:

  • Shapiro-Wilk 检验:在小样本量(如 $N < 2000$)时检验效力最强。
  • D'Agostino's K-squared 检验:基于偏度和峰度联合构造统计量,在大样本下更为可靠。
# 执行统计检验验证假设
stat_sw, p_sw = stats.shapiro(df["active_days"])
stat_dag, p_dag = stats.normaltest(df["order_amount"])

print("【活跃天数 - Shapiro-Wilk 检验】")
print(f"统计量: {stat_sw:.4f}, p值: {p_sw:.4f}")
if p_sw > 0.05:
    print("判定结论: p > 0.05,无法拒绝原假设,数据服从正态分布。")
else:
    print("判定结论: p <= 0.05,拒绝原假设,数据显著偏离正态分布。")

print("\n【订单金额 - D'Agostino K^2 检验】")
print(f"统计量: {stat_dag:.4f}, p值: {p_dag:.4e}")
if p_dag > 0.05:
    print("判定结论: p > 0.05,无法拒绝原假设,数据服从正态分布。")
else:
    print("判定结论: p <= 0.05,拒绝原假设,数据显著非正态。")
终端输出结果示例
【活跃天数 - Shapiro-Wilk 检验】 统计量: 0.9981, p值: 0.3218 判定结论: p > 0.05,无法拒绝原假设,数据服从正态分布。 【订单金额 - D'Agostino K^2 检验】 统计量: 312.4510, p值: 1.4190e-68 判定结论: p <= 0.05,拒绝原假设,数据显著非正态。

五、根据分布检查结果推导数据工程决策

完成关键指标与分布检查之后,不能停留在“写出几张图”的阶段,而是要形成具体的技术处理闭环:

Python探索性数据分析(EDA)怎么做?关键统计指标与分布检查
图 4:基于 EDA 统计指标与分布检查结果的技术决策路径

1. 针对右偏长尾数据的实际转换示例

对于如 order_amount 这类严重右偏特征,直接代入基于距离度量或线性可加性的算法(如 KNN、线性回归、神经元激活)通常表现欠佳。常见做法是对其进行对数变换(Log Transform):

# 执行对数平滑转换
df["order_amount_log"] = np.log1p(df["order_amount"])

print("转换前偏度:", round(df["order_amount"].skew(), 3))
print("转换后偏度:", round(df["order_amount_log"].skew(), 3))
终端输出结果示例
转换前偏度: 1.984 转换后偏度: 0.125

经过 log1p 变换后,偏度从 1.984 急剧下降至 0.125,原本拖拉的长尾被有效收敛,数据形态迅速接近对称正态分布。

六、EDA 实践中的高频陷阱与规避指南

常见陷阱 典型表现与风险 规范做法与应对方案
均值依赖陷阱 在强偏态分布中仅汇报平均数,导致业务评估严重偏离大众真实情况。 在计算均值的同时必须并行汇报中位数与 IQR;当两者差距过大时,以中位数作为代表值。
离群点草率删除 将所有超出箱线图须线的点当作错误数据全部过滤,丢失重要的核心业务事件(如大促巨额消费、设备故障信号)。 区分“数据录入错误”与“真实极端业务表现”。对真实极端值采用盖帽处理(Winsorization)或分桶,而非直接物理删除。
直方图分箱过粗/过细 分箱(bins)设为 5 导致所有结构被抹平;分箱设为 200 导致产生大量锯齿伪波峰。 结合 Freedman-Diaconis 经验法则确定分箱宽度:$\text{bin width} = 2 \times \text{IQR} \times n^{-1/3}$,并叠加平滑 KDE 曲线。
忽视大样本检验灵敏度 当样本量达到十万级别时,微弱的不规则波动就会使检验 p 值趋近于 0,机械判定为“非正态”。 在大数据量场景下以 Q-Q 图偏离程度与偏度绝对值为主观核心依据,假设检验结果仅作参考。
总结归纳
探索性数据分析并非无目的的图表堆砌,而是一场由表及里的验证过程:首先利用 shape 与 isna 锁定边界,接着计算均值、中位数、IQR、偏度与峰度构建量化基准,随后运用直方图、箱线图、Q-Q 图与 ECDF 排查分布细节与异常,最终得出该特征应该“对数平滑”、“稳健缩放”还是“拆解分群”的工程决策。建立起这套标准流程后,你便能在面对任意陌生数据集时,从容高效地推进建模准备。
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表