数据探索与可视化:先看看你的数据长什么样
拿到风电数据的第一件事是什么?不是急着调模型,而是先跟数据「打个招呼」。我个人的习惯是,先花半小时把数据摸一遍,看看它有没有「生病」。这步做好了,后面能省下大把的调试时间。
说白了,数据探索就像医生给病人做体检。你得先知道血压、心率、体温这些指标,才能判断哪里出了问题。风电数据也一样,传感器采集来的信号,可能带着噪声、缺失值,甚至还有异常点。我们这节课就来干这件事。
1. 加载CSV数据:第一步,把数据请进来
Python里加载CSV,最常用的就是pandas。我一般这么写:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 加载风电数据
df = pd.read_csv('wind_turbine_data.csv', parse_dates=['timestamp'])
print('数据加载完成,形状为:', df.shape)
这里有个小细节——parse_dates参数。我遇到过不少同学,数据加载完才发现时间列是字符串类型,后面处理起来特别麻烦。所以,加载时就指定时间列,省得后面再转换。
nrows=1000先预览前1000行,确认格式没问题再全量加载。我曾经一次加载了5GB的数据,结果发现列名对不上,白白浪费了半小时。
2. describe() 和 info():快速摸清数据底细
加载完数据,我习惯先跑两个函数:
# 查看数据基本信息
print(df.info())
# 查看数值型列的统计摘要
print(df.describe())
info()会告诉你每列的数据类型、非空值数量。嗯,这里要注意——如果某列显示object类型,但实际应该是数值,那就要检查是不是混入了字符串(比如「N/A」或「-」)。
describe()则给出均值、标准差、四分位数等统计量。我特别关注min和max这两行。举个例子,风速传感器的正常范围是0~30m/s,如果max显示100,那肯定有问题。
| 指标 | 风速(m/s) | 功率(kW) | 转速(rpm) |
|---|---|---|---|
| count | 10000 | 10000 | 10000 |
| mean | 8.5 | 1500 | 12.3 |
| std | 4.2 | 800 | 3.1 |
| min | 0.0 | -50 | 0.0 |
| max | 35.0 | 2500 | 20.0 |
你看,功率的min是-50,这明显不合理——功率不可能是负值。这就是异常值的信号。
3. 缺失值可视化:找到数据里的「黑洞」
风电数据里,缺失值很常见。传感器故障、通信中断、维护停机,都可能导致数据缺失。我习惯用热力图来可视化缺失情况:
import missingno as msno
# 缺失值矩阵图
msno.matrix(df)
plt.title('缺失值分布矩阵')
plt.show()
# 缺失值柱状图
msno.bar(df)
plt.title('各列缺失值数量')
plt.show()
为什么要可视化?因为光看数字不够直观。你想想看,如果缺失值集中在某段时间,那可能是那个时间段传感器出了问题。如果缺失值随机分布,那可能是偶发性的通信丢包。
4. 箱线图与异常值初探:揪出「捣乱分子」
箱线图是发现异常值的利器。它用四分位数来定义正常范围,超出1.5倍IQR(四分位距)的点就被标记为异常值。
# 绘制风速的箱线图
plt.figure(figsize=(10, 6))
sns.boxplot(x=df['wind_speed'])
plt.title('风速箱线图')
plt.show()
# 同时绘制多个特征
plt.figure(figsize=(12, 6))
sns.boxplot(data=df[['wind_speed', 'power', 'rotor_speed']])
plt.title('多个特征的箱线图对比')
plt.show()
箱线图能告诉你三件事:
- 数据的集中趋势:中位数在哪里
- 数据的离散程度:箱体有多宽
- 异常值的位置:那些孤零零的小圆点
举个例子,风速的箱线图显示上边缘是25m/s,但有几个点跑到了40m/s。这些点可能是极端天气,也可能是传感器故障。怎么区分?我会结合时间戳去看——如果这些点发生在台风天,那可能是真实数据;如果发生在风和日丽的下午,那八成是传感器抽风了。
5. 知识体系总览
下面这张图,把数据探索的核心流程串起来了:
这张图展示了数据探索的四个核心步骤,以及每个步骤需要关注的关键点。从加载数据开始,到基本信息查看,再到缺失值和异常值的识别,每一步都在为后续的异常检测打基础。
6. 实战小贴士:把这些代码串起来
最后,我分享一个我常用的「数据体检」模板。每次拿到新数据,我都会跑一遍:
def data_health_check(df):
"""数据健康检查函数"""
print("="*50)
print("1. 数据形状:", df.shape)
print("="*50)
print("\n2. 列信息:")
print(df.info())
print("\n3. 统计摘要:")
print(df.describe())
print("\n4. 缺失值统计:")
missing = df.isnull().sum()
missing_pct = (missing / len(df)) * 100
missing_df = pd.DataFrame({'缺失数量': missing, '缺失比例(%)': missing_pct})
print(missing_df[missing_df['缺失数量'] > 0])
# 绘制箱线图
numeric_cols = df.select_dtypes(include=[np.number]).columns[:6]
fig, axes = plt.subplots(2, 3, figsize=(15, 8))
axes = axes.flatten()
for i, col in enumerate(numeric_cols):
sns.boxplot(y=df[col], ax=axes[i])
axes[i].set_title(f'{col} 箱线图')
plt.tight_layout()
plt.show()
return missing_df
# 使用示例
missing_info = data_health_check(df)
这个函数会一口气输出数据的基本信息、统计摘要、缺失情况,还会自动绘制箱线图。我建议你把它保存下来,以后每个项目都能用。
- 加载数据时指定时间列,避免后续转换麻烦
- info()和describe()是快速了解数据的「体检报告」
- 缺失值可视化能发现规律性缺失,比单纯看数字更有价值
- 箱线图的异常值只是统计意义上的离群点,需要结合物理意义判断
数据探索这一步,说白了就是跟数据「混个脸熟」。你花的时间越多,后面建模就越顺。别急着跳过去,慢慢来,比较快。