3. 数据探索与可视化:描述性统计分析、数据分布与异常检测、可视化工具(Matplotlib/Seaborn)

各位同学,欢迎来到第三章。前两章我们聊了数据挖掘的全局观和怎么把脏数据洗干净。现在,数据已经躺在你面前了,下一步是什么?

我个人习惯,拿到任何数据集,第一件事不是急着建模,而是先跟数据「聊聊天」。怎么聊?就是做数据探索和可视化。说白了,你得先知道你的数据长什么样,有什么脾气,才能对症下药。

3.1 描述性统计分析:给数据做个体检

描述性统计,就是给数据做一次全面的体检。你想想看,去医院体检,是不是先量身高体重、测血压心率?数据也一样,我们需要知道它的集中趋势和离散程度。

3.1.1 集中趋势的度量

  • 均值(Mean):最常用的指标。但我提醒你,均值对异常值非常敏感。我在ATO系统里遇到过,某天一个闸机故障,交易量突然飙到正常值的100倍,均值瞬间被拉高,差点误导了后续的容量规划。
  • 中位数(Median):比均值稳健得多。如果你的数据分布偏斜严重,看中位数比看均值靠谱。
  • 众数(Mode):在ATO系统中,我们经常用众数来看最常见的乘客出行时段或最常使用的闸机。

3.1.2 离散程度的度量

  • 标准差(Std):数据波动有多大?标准差告诉你。我记得有一次分析某条线路的客流,标准差特别大,后来发现是早晚高峰的潮汐现象导致的。
  • 四分位距(IQR):Q3 - Q1。这个指标在异常检测里非常有用,后面会细说。
  • 极差(Range):最大值减最小值。简单粗暴,但容易受极端值影响。

核心经验:在ATO运营数据中,我建议你同时看均值和标准差。比如,平均交易时长是2秒,但标准差是5秒,说明系统存在严重的响应延迟问题,需要深挖。

3.2 数据分布与异常检测:揪出那些「不对劲」的数据

数据分布,就是数据在取值范围内的「长相」。有的数据长得像钟形(正态分布),有的像长尾(幂律分布)。在ATO系统里,乘客的等待时间、闸机的使用频率,往往都不是正态分布。

3.2.1 常见数据分布

分布类型 特点 ATO场景举例
正态分布 对称,中间高两边低 正常情况下,乘客通过闸机的时间
泊松分布 描述单位时间内随机事件发生的次数 每分钟到达某个站台的乘客数
长尾分布 大量数据集中在头部,少量在尾部 少数热门站点承担了大部分客流

3.2.2 异常检测实战方法

异常检测,说白了就是找「不一样」的数据点。在ATO系统里,异常数据可能意味着设备故障、网络攻击或者运营事故。

  1. Z-Score 方法:计算每个数据点距离均值多少个标准差。通常,Z-Score > 3 或 < -3 的被认为是异常。但要注意,这个方法假设数据是正态分布的,如果数据偏斜严重,效果会打折扣。
  2. IQR 方法:这是我个人最常用的方法。定义下界为 Q1 - 1.5*IQR,上界为 Q3 + 1.5*IQR。超出这个范围的就是异常点。我曾经用这个方法,成功揪出了某个闸机因为传感器老化导致的间歇性数据异常。
  3. 箱线图(Box Plot):可视化版本的IQR方法。一眼就能看出哪些点是离群值。

避坑指南:我曾经犯过一个错误,把所有异常点都直接删掉了。后来发现,有些「异常」其实是新业务模式导致的正常数据。比如,某条新线路开通后,客流激增,用旧模型看全是异常。所以,异常检测的结果一定要结合业务背景去判断,不要一刀切。

3.3 可视化工具:Matplotlib 与 Seaborn

数据探索,光看数字是不够的。一张好的图表,胜过千言万语。在Python生态里,Matplotlib是基础,Seaborn是它的高级封装,用起来更顺手。

3.3.1 Matplotlib:从零开始画图

Matplotlib 功能强大,但API相对底层。你想想看,它就像给你一堆乐高积木,你可以拼出任何形状,但需要自己动手。

import matplotlib.pyplot as plt
import numpy as np

# 生成模拟数据:ATO系统某闸机每小时交易量
hours = np.arange(0, 24)
transactions = [120, 85, 60, 45, 30, 25, 40, 150, 300, 450, 500, 480,
                420, 390, 410, 460, 520, 580, 620, 550, 400, 280, 180, 130]

plt.figure(figsize=(10, 5))
plt.plot(hours, transactions, marker='o', linestyle='-', color='b')
plt.title('某闸机24小时交易量趋势')
plt.xlabel('小时')
plt.ylabel('交易量')
plt.grid(True, alpha=0.3)
plt.show()

嗯,这里要注意,Matplotlib默认的样式比较朴素。我建议你设置一下样式,比如 plt.style.use('ggplot'),会让图表好看不少。

3.3.2 Seaborn:让统计图表更优雅

Seaborn 是建立在 Matplotlib 之上的,专门为统计可视化设计。它的API更简洁,默认配色也更舒服。我个人习惯,做探索性分析时,90%的情况都用Seaborn。

import seaborn as sns
import pandas as pd

# 模拟ATO系统乘客等待时间数据
data = {
    '站点': ['A站']*100 + ['B站']*100 + ['C站']*100,
    '等待时间': np.random.exponential(scale=2, size=100).tolist() +
               np.random.exponential(scale=5, size=100).tolist() +
               np.random.exponential(scale=1, size=100).tolist()
}
df = pd.DataFrame(data)

# 绘制箱线图,对比不同站点的等待时间分布
plt.figure(figsize=(8, 6))
sns.boxplot(x='站点', y='等待时间', data=df)
plt.title('不同站点乘客等待时间分布对比')
plt.show()

你看,三行代码就画出了一个漂亮的箱线图。B站的等待时间明显更长,而且有多个异常点。这提示我们,B站的闸机配置可能需要优化。

3.3.3 常用图表类型速查

图表类型 适用场景 Seaborn 函数
直方图 查看单变量的分布情况 sns.histplot()
箱线图 对比多组数据的分布和异常值 sns.boxplot()
散点图 查看两个变量之间的关系 sns.scatterplot()
热力图 展示相关性矩阵 sns.heatmap()
小提琴图 结合了箱线图和核密度估计 sns.violinplot()

小技巧:在探索数据时,我建议你先把所有数值型变量两两之间的散点图矩阵画出来。用 sns.pairplot() 一行代码就能搞定。这能帮你快速发现变量之间的线性关系、非线性关系或者聚类结构。

3.4 实战案例:ATO系统客流异常检测

好了,理论讲完了,我们来看一个完整的实战案例。假设我们拿到了某地铁站一周的客流数据,需要找出异常的日子。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 模拟一周客流数据(单位:万人次)
np.random.seed(42)
days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
passenger_flow = np.random.normal(loc=50, scale=5, size=7)
# 人为制造一个异常:周四客流异常低
passenger_flow[3] = 20

df_flow = pd.DataFrame({'日期': days, '客流': passenger_flow})

# 1. 描述性统计
print(df_flow['客流'].describe())

# 2. 可视化:箱线图
plt.figure(figsize=(8, 4))
sns.boxplot(y=df_flow['客流'])
plt.title('一周客流分布箱线图')
plt.show()

# 3. IQR异常检测
Q1 = df_flow['客流'].quantile(0.25)
Q3 = df_flow['客流'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

anomalies = df_flow[(df_flow['客流'] < lower_bound) | (df_flow['客流'] > upper_bound)]
print(f"检测到的异常日期:{anomalies['日期'].values}")

运行这段代码,你会发现周四被标记为异常。为什么?因为它的客流只有20万,远低于正常水平。结合业务分析,可能是那天发生了设备故障或者临时限流。

你看,通过简单的描述性统计、箱线图和IQR方法,我们就快速定位了问题。这就是数据探索的魅力——它让你在建模之前,就对数据有了深刻的理解。

总结一下:数据探索不是走过场,它是整个数据挖掘项目的基石。你花在探索上的每一分钟,都会在后续建模和部署阶段得到回报。记住,永远不要在一个你不理解的数据集上直接建模。

下一章,我们会进入特征工程的环节,聊聊怎么从原始数据中提取出真正有用的特征。到时候见!


公众号:蓝海资料掘金营,微信deep3321