3. 数据采集与探索性分析(EDA)
好,咱们正式开始动手了。这一章我带你走一遍数据采集和探索性分析的全流程。说白了,就是先把原料搞到手,再翻来覆去地看看它到底长什么样。我做了这么多年模型,有个深刻的体会:数据质量决定了模型的天花板。你后面调参调得再好,也弥补不了数据本身的硬伤。
3.1 数据来源介绍:UCI 与 OpenAQ
做空气质量预测,数据从哪来?我个人最常用的两个渠道:UCI 机器学习库和 OpenAQ 平台。
- UCI 数据集:经典、干净、适合练手。比如那个“北京 PM2.5 数据集”,包含了 2010-2014 年北京的气象数据和 PM2.5 浓度。我当年入门时就是拿它做的第一个回归模型。
- OpenAQ 平台:实时、全球、更真实。它聚合了全球各地政府监测站的实时数据。嗯,这里要注意:OpenAQ 的数据比较“野”,缺失值和异常值会更多,但做工业级项目时,我建议你直接上这个。
我的建议: 初学者先用 UCI 数据跑通流程,再挑战 OpenAQ 的“脏数据”。我在项目中遇到过,直接拿 OpenAQ 数据建模,结果 30% 的时间都花在了清洗上。
3.2 数据加载与初步查看
数据拿到手,第一件事就是把它加载进来。我用 Python 的 pandas 库,几行代码搞定。
import pandas as pd
# 加载 UCI 北京 PM2.5 数据集
df = pd.read_csv('BeijingPM20100101_20151231.csv')
# 看一眼前 5 行
print(df.head())
# 看看数据集的形状
print(f"数据集维度: {df.shape}")
你想想看,这一步其实就是在“验货”。head() 能让你快速感知数据长什么样——列名对不对、数值范围是否合理。我习惯紧接着用 info() 看看每列的数据类型和非空情况。
print(df.info())
为什么会这样?因为很多时候你拿到的 CSV 文件,日期列被读成了字符串,或者数值列里混进了“NA”这样的文本。这一步能帮你提前发现很多坑。
3.3 描述性统计与数据质量报告
接下来,我要给数据做个“体检”。describe() 是最常用的工具。
# 描述性统计
print(df.describe())
它会输出每列的计数、均值、标准差、最小值、四分位数和最大值。我一般重点关注三点:
- 计数(count):如果某列计数远小于总行数,说明缺失严重。
- 最小值/最大值:PM2.5 浓度出现负数?那肯定有问题。
- 标准差:如果某列标准差为 0,说明它是个常数,对模型没贡献。
小技巧: 我习惯自己写一个简单的数据质量报告函数,把缺失率、唯一值数量、数据类型都汇总到一张表里。这样一眼就能看出哪些列需要处理。
3.4 缺失值与异常值初步识别
这一步是 EDA 的重头戏。我先说缺失值。
# 检查每列的缺失值数量
print(df.isnull().sum())
# 计算缺失率
print((df.isnull().sum() / len(df)) * 100)
我曾经在一个项目中,发现某列缺失率高达 60%。当时我第一反应不是直接删除,而是去查了数据采集日志——原来是那段时间传感器故障了。嗯,这里要注意:缺失值背后往往有故事,别急着填。
再来看异常值。我常用的方法是画箱线图,或者用 3σ 原则。
# 用 IQR 方法识别异常值
Q1 = df['PM2.5'].quantile(0.25)
Q3 = df['PM2.5'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df['PM2.5'] < lower_bound) | (df['PM2.5'] > upper_bound)]
print(f"检测到 {len(outliers)} 个异常值")
避坑指南: 我曾经直接把所有异常值删掉,结果模型在极端污染天气下预测效果极差。后来才明白,对于空气质量数据,极端值往往是最需要预测的场景。所以,先标记,别急着删。
知识体系总览
下面这张图,是我自己梳理的本章知识结构。你可以把它当作一个检查清单。
这张图把本章的四个核心环节串起来了。你从数据来源开始,一路走到缺失值和异常值的识别,每一步都有对应的工具和方法。我个人建议你把这个流程固化下来,以后做任何数据项目都可以复用。