4. 单变量特征分析:描述性统计、分布可视化与偏度峰度

单变量分析是特征工程的起点,其核心目标是通过统计量与图形快速评估单个特征的数据质量、分布形态与异常倾向。本节将系统讲解描述性统计指标、直方图与箱线图的解读方法,以及偏度与峰度的计算与业务含义。

4.1 描述性统计:集中趋势与离散程度

描述性统计用一组简洁的数值概括特征的全貌,通常分为集中趋势与离散程度两类指标。

类别 指标 定义 适用场景
集中趋势 均值(Mean) 所有观测值的算术平均 对称分布、无极端值
中位数(Median) 排序后位于中间位置的值 偏态分布、含异常值
众数(Mode) 出现频率最高的值 分类特征、离散型数值
离散程度 标准差(Std) 数据偏离均值的平均程度 衡量波动性
四分位距(IQR) Q3 - Q1,中间50%数据的跨度 稳健离散度量,不受异常值影响
极差(Range) 最大值 - 最小值 快速了解数据跨度
关键判断规则: 当均值与中位数差异超过标准差的 0.1 倍时,应警惕分布偏斜或异常值干扰。

4.2 分布可视化:直方图与箱线图

图形比数字更直观地揭示分布形态。直方图展示数据的整体形状(对称、左偏、右偏、双峰),箱线图则聚焦于异常值与分位数结构。

4.2.1 直方图解读要点

  • 箱宽(bin width):过小导致噪声,过大掩盖细节;常用 Freedman-Diaconis 规则:bin_width = 2 * IQR * n^(-1/3)。
  • 分布形态:正态分布呈钟形;右偏(正偏)时尾部在右侧;左偏(负偏)时尾部在左侧。
  • 多峰:暗示数据可能来自不同子群体,需进一步分层分析。

4.2.2 箱线图异常值判定

箱线图使用四分位距(IQR)定义异常值边界:

下边界 = Q1 - 1.5 * IQR
上边界 = Q3 + 1.5 * IQR
温和异常值:落在 [下边界, Q1) 或 (Q3, 上边界] 区间
极端异常值:超出上下边界
实践建议: 对于业务特征,不要直接删除异常值。先标记异常值对应的样本,结合业务逻辑判断是数据录入错误、真实极端事件还是传感器故障。
直方图与箱线图对比(右偏分布示例) 直方图 低值 高值 异常尾部 箱线图 中位数 Q3 Q1 上边界 下边界 异常值 箱线图关键信息 箱体 = IQR 范围(Q1~Q3) 须线 = 1.5×IQR 边界,之外为异常值

4.3 偏度与峰度计算

偏度(Skewness)与峰度(Kurtosis)是量化分布形态的两个高阶矩统计量,在特征工程中用于判断正态性偏离程度与尾部风险。

4.3.1 偏度(Skewness)

偏度衡量分布不对称性的方向与程度:

偏度公式:γ₁ = (1/n) * Σ[(xᵢ - μ)³] / σ³

判断标准:
  γ₁ = 0   → 对称分布(如正态分布)
  γ₁ > 0   → 右偏(正偏),尾部在右侧,均值 > 中位数
  γ₁ < 0   → 左偏(负偏),尾部在左侧,均值 < 中位数

经验阈值:
  |γ₁| < 0.5   → 近似对称
  0.5 ≤ |γ₁| < 1 → 中等偏态
  |γ₁| ≥ 1     → 高度偏态,需考虑变换

4.3.2 峰度(Kurtosis)

峰度衡量分布尾部厚度与峰部尖锐度,通常使用超额峰度(Excess Kurtosis):

峰度公式:γ₂ = (1/n) * Σ[(xᵢ - μ)⁴] / σ⁴ - 3

判断标准:
  γ₂ = 0   → 正态分布(Mesokurtic)
  γ₂ > 0   → 尖峰厚尾(Leptokurtic),异常值风险高
  γ₂ < 0   → 平峰薄尾(Platykurtic),分布更均匀

业务含义:
  金融特征中,峰度 > 3 常预示极端波动风险
  传感器特征中,峰度 > 5 可能指示噪声或故障
常见误区: 峰度高 ≠ 分布更“尖”。峰度主要由尾部极端值贡献,而非中心峰值高度。两个分布中心高度相同,但尾部更厚的分布峰度更高。

4.4 单变量分析流程总结

以下流程将描述性统计、可视化与偏度峰度整合为可复用的分析管线:

  1. 快速扫描:计算均值、中位数、标准差、IQR,检查均值与中位数差异。
  2. 分布可视化:绘制直方图(观察整体形状)与箱线图(标记异常值)。
  3. 量化偏斜:计算偏度,若 |γ₁| ≥ 1 则记录为“需变换特征”。
  4. 评估尾部风险:计算超额峰度,若 γ₂ > 2 则标记为“厚尾特征”。
  5. 决策记录:将分析结果写入特征元数据表,供后续特征变换(如对数变换、Box-Cox)参考。
偏度与峰度形态对比 左偏(负偏) 尾部在左 均值 < 中位数 对称(正态) 偏度 ≈ 0 峰度 ≈ 0 右偏(正偏) 尾部在右 均值 > 中位数 尖峰厚尾(峰度 > 0) 异常值 平峰薄尾(峰度 < 0) 尾部薄,无极端值 正态峰度(峰度 = 0) 参考基准

4.5 实战代码示例

以下 Python 代码演示单变量分析的完整流程,使用 pandas、scipy.stats 与 matplotlib:

import pandas as pd
import numpy as np
from scipy.stats import skew, kurtosis
import matplotlib.pyplot as plt

def univariate_analysis(df, feature):
    """
    对指定特征执行单变量分析,返回统计指标与诊断建议。
    """
    data = df[feature].dropna()
    n = len(data)
    mean = np.mean(data)
    median = np.median(data)
    std = np.std(data, ddof=1)
    q1 = np.percentile(data, 25)
    q3 = np.percentile(data, 75)
    iqr = q3 - q1
    skew_val = skew(data)
    kurt_val = kurtosis(data, fisher=True)  # 超额峰度

    # 诊断规则
    mean_median_diff = abs(mean - median) / std
    skew_flag = "高度偏态" if abs(skew_val) >= 1 else ("中等偏态" if abs(skew_val) >= 0.5 else "近似对称")
    kurt_flag = "尖峰厚尾" if kurt_val > 0 else ("平峰薄尾" if kurt_val < 0 else "正态峰度")

    # 异常值计数
    lower_bound = q1 - 1.5 * iqr
    upper_bound = q3 + 1.5 * iqr
    outlier_count = np.sum((data < lower_bound) | (data > upper_bound))

    result = {
        "特征": feature,
        "样本量": n,
        "均值": round(mean, 4),
        "中位数": round(median, 4),
        "标准差": round(std, 4),
        "偏度": round(skew_val, 4),
        "偏度诊断": skew_flag,
        "超额峰度": round(kurt_val, 4),
        "峰度诊断": kurt_flag,
        "异常值个数": outlier_count,
        "异常值占比(%)": round(outlier_count / n * 100, 2)
    }
    return result

# 使用示例
# result = univariate_analysis(df, "age")
# print(result)

# 可视化
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
axes[0].hist(df["age"], bins=30, color="#3498db", edgecolor="#2980b9")
axes[0].set_title("直方图")
axes[1].boxplot(df["age"].dropna(), vert=True, patch_artist=True,
                boxprops=dict(facecolor="#1abc9c", color="#16a085"))
axes[1].set_title("箱线图")
plt.tight_layout()
plt.show()
输出解读: 若偏度诊断结果为“高度偏态”且峰度诊断结果为“尖峰厚尾”,则该特征不适合直接输入线性模型,建议优先尝试对数变换或 Box-Cox 变换。