数据质量评估:储能系统的第一道防线
做储能数据这么多年,我有个深刻的体会:数据质量决定了模型的天花板。你算法再牛,喂进去一堆垃圾数据,出来的结果也是垃圾。今天我们就聊聊数据质量评估这件事,说白了就是给你的数据做个全面体检。
核心观点:数据质量评估不是一次性工作,而是贯穿整个数据生命周期的持续过程。我建议每个项目开始前,至少花20%的时间做数据质量摸底。
1. 数据完整性检查
完整性检查,就是看看数据有没有缺胳膊少腿。我在一个大型储能电站项目里遇到过,采集系统因为网络波动,每天凌晨2点到4点的数据经常丢失。如果不做完整性检查,模型训练出来就是个瘸子。
具体怎么做?我一般从三个维度入手:
- 时间维度:检查时间戳是否连续,有没有跳变
- 字段维度:每个字段是否有值,不能是空字符串或NaN
- 记录维度:实际记录数是否等于预期记录数
举个代码例子,这是我常用的完整性检查脚本:
import pandas as pd
import numpy as np
def check_data_completeness(df, expected_freq='1min'):
"""
数据完整性检查函数
df: DataFrame,必须包含'timestamp'列
expected_freq: 期望的数据频率,默认1分钟
"""
# 1. 检查时间连续性
df['timestamp'] = pd.to_datetime(df['timestamp'])
df = df.set_index('timestamp').sort_index()
# 生成完整的时间序列
full_time_range = pd.date_range(
start=df.index.min(),
end=df.index.max(),
freq=expected_freq
)
# 找出缺失的时间点
missing_times = full_time_range.difference(df.index)
# 2. 检查字段完整性
null_counts = df.isnull().sum()
null_ratio = null_counts / len(df) * 100
# 3. 输出结果
print(f"总记录数: {len(df)}")
print(f"期望记录数: {len(full_time_range)}")
print(f"缺失时间点: {len(missing_times)}")
print(f"缺失率: {len(missing_times)/len(full_time_range)*100:.2f}%")
print("\n各字段缺失比例:")
print(null_ratio)
return missing_times, null_ratio
我的小技巧:对于储能数据,我习惯把完整性检查做成定时任务,每天跑一次。这样能第一时间发现采集系统的问题,而不是等到建模时才发现数据有问题。
2. 缺失值比例统计
缺失值处理,说白了就是决定哪些数据能用,哪些不能用。我见过有人一上来就用均值填充,结果把异常值当正常值处理了,模型效果一塌糊涂。
我的经验是:先统计缺失比例,再决定处理策略。
| 缺失比例 | 处理策略 | 适用场景 |
|---|---|---|
| < 5% | 直接删除或简单填充 | 数据量大,缺失随机 |
| 5% - 20% | 插值法或模型预测填充 | 时间序列数据,有规律可循 |
| 20% - 50% | 标记为特殊值,单独建模 | 传感器故障,数据不可靠 |
| > 50% | 直接丢弃该特征 | 信息量太少,留着也没用 |
为什么会这样?你想想看,如果一个传感器有超过一半的数据都是缺失的,那这个传感器基本可以判定为失效了。我曾经在一个项目中,某个温度传感器的缺失率高达60%,后来发现是接线松动导致的。
3. 异常值检测
异常值检测,这是数据质量评估的重头戏。我主要用两种方法:3σ原则和IQR方法。
3.1 3σ原则
3σ原则,说白了就是假设数据服从正态分布,超出均值±3倍标准差的数据就是异常值。这个方法简单粗暴,但有个前提:数据要近似正态分布。
def detect_outliers_3sigma(df, column):
"""
使用3σ原则检测异常值
"""
mean = df[column].mean()
std = df[column].std()
lower_bound = mean - 3 * std
upper_bound = mean + 3 * std
outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
print(f"特征: {column}")
print(f"均值: {mean:.2f}, 标准差: {std:.2f}")
print(f"正常范围: [{lower_bound:.2f}, {upper_bound:.2f}]")
print(f"异常值数量: {len(outliers)}")
print(f"异常值比例: {len(outliers)/len(df)*100:.2f}%")
return outliers
注意:3σ原则对极端值非常敏感。如果数据本身就有很多异常值,均值和标准差会被拉偏,导致检测效果变差。我建议先用IQR方法做一轮粗筛,再用3σ原则做精筛。
3.2 IQR方法
IQR方法,也就是四分位距法。它不依赖数据分布假设,鲁棒性更好。具体来说:
- 计算第一四分位数Q1和第三四分位数Q3
- IQR = Q3 - Q1
- 正常范围:[Q1 - 1.5*IQR, Q3 + 1.5*IQR]
- 超出这个范围的就是异常值
def detect_outliers_iqr(df, column):
"""
使用IQR方法检测异常值
"""
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
print(f"特征: {column}")
print(f"Q1: {Q1:.2f}, Q3: {Q3:.2f}, IQR: {IQR:.2f}")
print(f"正常范围: [{lower_bound:.2f}, {upper_bound:.2f}]")
print(f"异常值数量: {len(outliers)}")
print(f"异常值比例: {len(outliers)/len(df)*100:.2f}%")
return outliers
避坑指南:我曾经在一个储能项目中,用3σ原则检测SOC(荷电状态)的异常值,结果把正常的充放电转换点都标记为异常了。后来改用IQR方法,效果就好很多。所以,方法没有好坏,关键看数据特点。
4. 数据一致性校验
一致性校验,就是看看不同传感器之间的数据是否对得上。我在一个项目中遇到过,两个相邻的温度传感器,一个显示25度,一个显示35度,差了10度。后来发现是其中一个传感器安装位置不对,被太阳直射了。
常用的校验方法:
- 交叉验证:对比同一物理量的不同传感器数据
- 物理约束:检查数据是否符合物理规律(比如电压不能为负)
- 时间对齐:确保不同传感器的时间戳一致
def check_consistency(df, sensor1, sensor2, threshold=0.1):
"""
检查两个传感器的数据一致性
threshold: 允许的最大相对偏差
"""
# 计算相对偏差
relative_diff = abs(df[sensor1] - df[sensor2]) / df[sensor2]
# 找出不一致的数据点
inconsistent = df[relative_diff > threshold]
print(f"传感器1: {sensor1}, 传感器2: {sensor2}")
print(f"允许最大相对偏差: {threshold*100}%")
print(f"不一致数据点: {len(inconsistent)}")
print(f"不一致比例: {len(inconsistent)/len(df)*100:.2f}%")
return inconsistent
知识体系总览
说了这么多,我画了一张图来总结数据质量评估的核心逻辑。嗯,你看完应该就清楚了:
数据质量评估这件事,说白了就是给你的数据做体检。完整性检查看有没有缺数据,缺失值统计看缺了多少,异常值检测看数据有没有问题,一致性校验看不同传感器是否打架。这四个步骤走下来,你的数据基本就干净了。
记住一句话:数据质量决定了模型的天花板。花时间把数据质量搞好了,后面的建模工作才能事半功倍。