第二章:数据探索与可视化——风电数据特征(风速、风向、温度、气压)、数据分布分析、异常值初步识别
各位同学,欢迎来到实战课的第二站。上一章我们聊了风电功率预测的整体框架,今天咱们要干点“脏活累活”——数据探索。
说实话,我见过太多人一上来就调模型、跑算法,结果模型死活不收敛。为什么?因为数据本身就有问题。你想想看,如果输入的风速数据里混着几个传感器故障的“野值”,模型学到的全是噪音,怎么可能预测准?
所以,这一章的核心就一句话:先摸清数据的脾气,再谈调参。
本章核心目标:
- 理解风电数据的5大特征(风速、风向、温度、气压、功率)
- 掌握数据分布分析方法(直方图、箱线图、Q-Q图)
- 学会异常值的初步识别与处理
2.1 风电数据的5大特征
先说说风电数据里最常见的几个特征。我做了这么多年项目,发现不管哪个风场,核心特征就这5个:
| 特征名称 | 单位 | 典型范围 | 对功率的影响 |
|---|---|---|---|
| 风速 | m/s | 0 ~ 30 | 核心因素,呈三次方关系 |
| 风向 | ° | 0 ~ 360 | 影响尾流效应和偏航控制 |
| 温度 | ℃ | -20 ~ 40 | 影响空气密度,间接影响功率 |
| 气压 | hPa | 950 ~ 1050 | 影响空气密度 |
| 有功功率 | kW | 0 ~ 额定功率 | 目标变量 |
这里我要特别强调一下风向。很多新手觉得风向就是个角度,直接扔进模型就行。其实不是的。风向是环形数据,0°和360°其实是一个方向。我早期有个项目,直接把风向当线性特征处理,结果模型在0°附近预测总是出错。后来改成正弦余弦编码,问题就解决了。
小技巧:处理风向时,建议拆成 sin(风向) 和 cos(风向) 两个特征。这样既能保留方向信息,又避免了0°和360°的跳变问题。
2.2 数据分布分析——先看看数据长什么样
拿到数据后,我习惯先画分布图。为什么?因为分布图能告诉你很多信息:数据是否偏态?有没有多峰?有没有异常值?
2.2.1 风速分布——典型的威布尔分布
风速数据有个特点:它通常服从威布尔分布。什么意思呢?就是大部分时间风速在3-8 m/s之间,偶尔会有大风,但很少超过25 m/s。
我给大家看一段代码,画风速的直方图和概率密度曲线:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
# 假设 df 是包含风速数据的DataFrame
plt.figure(figsize=(10, 6))
# 直方图 + 核密度估计
sns.histplot(df['风速'], bins=50, kde=True, color='steelblue')
plt.title('风速分布直方图', fontsize=14)
plt.xlabel('风速 (m/s)', fontsize=12)
plt.ylabel('频数', fontsize=12)
plt.grid(True, alpha=0.3)
plt.show()
# 打印统计量
print(f"风速均值: {df['风速'].mean():.2f} m/s")
print(f"风速中位数: {df['风速'].median():.2f} m/s")
print(f"风速标准差: {df['风速'].std():.2f} m/s")
print(f"风速偏度: {df['风速'].skew():.2f}")
运行这段代码,你会看到风速分布通常是右偏的——也就是左边高、右边拖个长尾巴。偏度值一般在0.5到1.5之间。如果偏度太大,说明数据里可能有异常值。
2.2.2 风向分布——看看风从哪里来
风向分布用玫瑰图最直观。不过咱们先看简单的直方图:
plt.figure(figsize=(10, 6))
sns.histplot(df['风向'], bins=36, kde=False, color='orange')
plt.title('风向分布直方图', fontsize=14)
plt.xlabel('风向 (°)', fontsize=12)
plt.ylabel('频数', fontsize=12)
plt.xticks(range(0, 361, 45))
plt.grid(True, alpha=0.3)
plt.show()
嗯,这里要注意。如果风向分布出现明显的“尖峰”,比如某个方向频数特别高,那可能是风场的地形导致的。我在内蒙古一个风场遇到过这种情况——因为山脉走向,90%的风都从西北方向来。这种情况下,模型需要特别关注主风向的预测精度。
2.2.3 箱线图——快速发现异常值
箱线图是我最常用的工具之一。它能同时展示中位数、四分位数和异常值。
plt.figure(figsize=(12, 6))
# 画多个特征的箱线图
features = ['风速', '温度', '气压', '有功功率']
df[features].boxplot()
plt.title('主要特征箱线图', fontsize=14)
plt.xticks(rotation=45)
plt.grid(True, alpha=0.3)
plt.show()
箱线图里,超出上下须的点就是潜在的异常值。一般来说,上须 = Q3 + 1.5*IQR,下须 = Q1 - 1.5*IQR。超出这个范围的点,我会标记出来进一步检查。
注意:箱线图标记的异常值不一定是错误数据。比如风速在台风天达到30 m/s,虽然超出正常范围,但它是真实数据。所以异常值识别要结合业务知识,不能一刀切。
2.3 异常值初步识别——哪些数据需要警惕?
异常值处理是数据清洗的第一步。我把它分成三类:
- 物理极限异常:风速为负值、温度超过传感器量程等
- 统计异常:超出3σ范围或箱线图边界的值
- 业务异常:风速很高但功率很低(可能风机停机或限电)
2.3.1 3σ原则——简单粗暴但有效
对于近似正态分布的数据,可以用3σ原则:
def detect_outliers_3sigma(data, column):
mean = data[column].mean()
std = data[column].std()
lower_bound = mean - 3 * std
upper_bound = mean + 3 * std
outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
return outliers
# 检测风速异常值
wind_outliers = detect_outliers_3sigma(df, '风速')
print(f"风速异常值数量: {len(wind_outliers)}")
print(f"异常值范围: 小于 {df['风速'].mean() - 3*df['风速'].std():.2f} 或大于 {df['风速'].mean() + 3*df['风速'].std():.2f}")
不过我要提醒你,风速数据本身是偏态的,用3σ可能会漏掉一些异常。我个人的习惯是:先用3σ筛一遍,再用箱线图筛一遍,取并集。
2.3.2 IQR方法——对偏态数据更友好
IQR方法不假设数据是正态分布,所以对风速这种偏态数据更适用:
def detect_outliers_iqr(data, column):
Q1 = data[column].quantile(0.25)
Q3 = data[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
return outliers, lower_bound, upper_bound
outliers_iqr, lb, ub = detect_outliers_iqr(df, '风速')
print(f"IQR方法检测到异常值: {len(outliers_iqr)} 个")
print(f"正常范围: [{lb:.2f}, {ub:.2f}]")
2.3.3 业务规则——经验之谈
除了统计方法,我还依赖一些业务规则。比如:
- 风速-功率曲线检查:风速在切入风速以下(通常3 m/s)但功率不为0,或者风速在额定风速以上但功率远低于额定值,这些都需要标记
- 变化率检查:1秒内风速变化超过10 m/s,大概率是传感器故障
- 缺失值检查:连续多个时间点数据为0或NaN,可能是通讯中断
我曾经踩过的坑:有一次模型训练效果很好,但上线后预测偏差很大。排查了三天,发现是数据预处理时把“风速为0但功率不为0”的数据当异常删掉了。实际上那是风机在低风速下靠惯性发电的正常数据。所以,异常值处理一定要结合业务场景,不能只看统计指标。
2.4 实战建议——数据探索的标准化流程
最后,我总结一下数据探索的标准化流程,供大家参考:
- 第一步:概览——用 df.info() 和 df.describe() 了解数据基本情况
- 第二步:单变量分布——画每个特征的直方图和箱线图
- 第三步:双变量关系——画风速-功率散点图,看是否呈现预期的三次方关系
- 第四步:异常值标记——用3σ和IQR方法标记异常,结合业务规则确认
- 第五步:记录日志——把发现的异常和处理的决策记录下来,方便后续复盘
记住一句话:数据探索花的时间,会在模型训练阶段加倍还给你。我见过太多人急着调参,结果数据质量不过关,调来调去都是白费功夫。
好了,这一章的内容就到这里。数据探索是基本功,但也是最容易被忽视的环节。希望大家在实际项目中,能沉下心来把数据摸透。下一章我们会聊特征工程,到时候会用到今天发现的这些数据特性。