第2章:原始数据探索:数据类型、分布分析与可视化基础

拿到一批原始数据,别急着往上套模型。我个人的习惯是,先花点时间跟数据“聊聊天”。你得知道它长什么样,有哪些成分,有没有“坏掉”的地方。这一步虽然在课程里只占一章,但在实际项目里,我见过有人因为跳过了这个环节,后面整个管线跑飞了,最后才发现是数据格式读错了。

2.1 数据类型:数值、类别与文本

数据进了内存,程序只会看到一堆数字或者字符串。但从处理逻辑上说,得分清楚它们真正的“身份”。

类型 子类 例子 处理方式
数值型 连续 / 离散 价格、温度、年龄 缩放、填补、分箱
类别型 有序 / 无序 颜色、国家、评级 编码、嵌入
文本型 短文本 / 长文本 评论、摘要、日志 TF-IDF、词嵌入
时间序列 等间隔 / 不等间隔 股价、传感器读数 重采样、滑动窗口

为什么要区分这么细?举个例子,“邮政编码”看起来是数字,但你拿出来做除法或者求平均值就闹笑话了。我在项目中遇到过有人把地区ID当数值做线性回归,结果模型学得一团糟——因为它本质上是个无序类别。

我的小技巧:拿到数据后,先用 df.dtypes 扫一眼。如果pandas给你标了 object,别急着当字符串处理,先看看里面是不是藏着数值或者日期。

2.2 分布分析:你看到的不一定是真的

统计量容易骗人。均值100、方差20的数据集,跟均值100、方差20但其实是双峰分布的数据集,完全是两码事。我建议从两个角度入手。

2.2.1 基本统计量

用 df.describe() 能快速拿到均值、标准差、四分位数。但我一般还会多看一眼:

  • 缺失率:超过30%的列,你得认真考虑要不要保留。
  • 零值占比:很多传感器数据里,零值其实是缺失信号。
  • 极值:max 是不是比 99% 分位数大了好几个数量级?
import pandas as pd

df = pd.read_csv('raw_sensor.csv')
print(df.describe())

# 再查一下缺失和零值
missing_ratio = df.isnull().mean()
zero_ratio = (df == 0).mean()

2.2.2 分布的形状

数值分布长什么样,直接决定了你用哪种缩放策略。我见过一个场景,特征是长尾分布,直接做标准化后,大部分数据被压在一个小范围内,模型的收敛速度慢得离谱。

经验规律:

  • 正态/近似正态 → 用Z-score标准化
  • 偏态/长尾 → 先用对数变换或Box-Cox
  • 双峰/多峰 → 考虑分箱或分离建模

注意:对数变换只适用于正值。如果数据里有0或负数,得先做偏移。我曾经因为没注意这个,直接导致变换后出现NaN,排查了半天。

2.3 可视化基础:一张图胜过千行日志

统计数字说“均值是5”,但你画出来一看,所有点都在0和10两端,中间是空的——这种事情我碰上过好几次。可视化不是可有可无的装饰,它是你发现数据病灶的听诊器。

2.3.1 单变量分布图

  • 直方图:看整体形状,选合适的bin数量。默认的10个bin经常不够细。
  • 密度图:平滑版本,适合比较多个分布。
  • 箱线图:快速定位异常值和外点。
import matplotlib.pyplot as plt
import seaborn as sns

fig, axes = plt.subplots(1, 3, figsize=(14, 4))

sns.histplot(df['value'], bins=30, ax=axes[0])
axes[0].set_title('Histogram')

sns.kdeplot(df['value'], ax=axes[1])
axes[1].set_title('Density')

sns.boxplot(x=df['value'], ax=axes[2])
axes[2].set_title('Boxplot')

plt.tight_layout()
plt.show()

2.3.2 双变量关系图

我习惯先画一个散点图矩阵(pairplot),大概看看哪些特征跟目标变量有关联。但样本量大的时候,散点图会变成一团墨——这时候改用六边形分箱图或者抽样画。

# 抽样后绘图,避免过密
sample = df.sample(1000, random_state=42)
sns.scatterplot(data=sample, x='feature_1', y='feature_2', hue='label', alpha=0.6)

为什么我强调先可视化再动手?因为统计量不能告诉你数据里有没有“离群簇”——一群人聚在远离主体的地方,均值、方差都跟主群体差不多,但行为模式完全不同。这种分布上的“细腰”形态,只有画出来才看得到。

2.4 知识体系结构图

把这一章的内容串起来,大概是这样的流程:

原始数据探索知识结构 原始数据探索管线 原始数据集 1. 数据类型判断 数值型 类别型 文本型 2. 分布分析 反馈:清洗 / 变换 / 编码策略 可视化驱动每个决策

你想想看,整个流程其实是个回环。分布分析和可视化会暴露数据的问题,然后你回到最上面,重新调整类型判断——比如把原本当成数值的ID改成类别,或者把被漏掉的文本列抽出来。嗯,这里要注意的是,别一次性做太多人工干预,每次只改一两个点,保持可追溯性。

2.5 实战中我踩过的坑

最后分享几个我实际碰到的教训:

  • 缺省的“0”:温度传感器在故障时输出0,但气温本来就可能到0度。不看分布图,你不会发现那些“0值”其实分成了两群——真0度 vs 故障0。
  • 乱码文本:文本型数据里偶尔掺杂一些编码错误的字节。不画个词频图根本发现不了,因为日常检查只会看前几行。
  • 过高的可视化密度:10万个点全画上去,什么规律都看不到。我后来习惯了抽样+透明度+bins三层组合拳。

避坑指南:我曾经把含有缺失值的列直接用均值填充,没先画分布图看填充前后的变化。结果均值把右偏分布的中心拉偏了,后面的模型全白训。这事的教训是:填补之前,一定要先看分布,想清楚缺失机制是随机缺失还是非随机缺失。