第1章:数据清洗与预处理——储能运维的“地基工程”

大家好,我是老张,在储能行业摸爬滚打了十来年。今天咱们聊聊数据清洗与预处理。说实话,这活儿看着不起眼,但它是整个数据分析的“地基”。地基没打好,后面建多高的楼都得塌。

我记得刚入行那会儿,接过一个储能电站的运维数据,几十万条记录,看着挺唬人。结果一跑模型,出来的结果完全不对。后来排查了三天,发现是某个传感器在凌晨2点到4点之间,因为温度漂移,数据全偏了。嗯,从那以后,我再也不敢跳过数据清洗这一步了。

核心观点:数据清洗不是“打扫卫生”,而是“数据治理”。它决定了后续分析的准确性和可靠性。

1.1 缺失值处理——别让“空白”骗了你

储能系统的数据采集,说白了就是各种传感器在干活。但传感器也会“偷懒”——比如网络中断、设备故障、人为误操作,都会导致数据缺失。你想想看,一个锂电池的电压数据,如果中间缺了半小时,那SOC(荷电状态)估算就全乱了。

常见的缺失值类型:

  • 完全随机缺失:比如传感器被鸟撞了,纯属意外。这种可以直接删除或插补。
  • 随机缺失:比如温度过高导致传感器暂时失效。这种需要根据其他变量来推测。
  • 非随机缺失:比如人为故意删除了异常数据。这种最麻烦,得结合业务逻辑判断。

我的处理习惯:

  1. 先看缺失比例:如果某个字段缺失超过30%,我一般直接扔掉。别心疼,留着也是祸害。
  2. 再看缺失模式:用热力图或者矩阵图看看缺失值是不是有规律。比如是不是每天固定时间点缺失?那可能是定时维护导致的。
  3. 最后选方法:
    • 连续型数据(如电压、电流):我常用线性插值或前向填充。比如电压在10:00是3.2V,10:02是3.3V,那10:01的缺失值就填3.25V。
    • 离散型数据(如开关状态):用众数填充。比如90%的时间开关是“开”,那缺失值就填“开”。
    • 时间序列数据:用KNN插补或者时间序列分解。这个稍微复杂点,但精度高。

小技巧:我在项目中遇到过一种情况——缺失值其实不是“缺失”,而是“0”。比如某个电池簇的电流为0,可能是真的没放电,也可能是传感器坏了。这时候一定要结合其他簇的数据来交叉验证。

# Python示例:线性插值处理缺失值
import pandas as pd
import numpy as np

# 模拟储能电压数据
data = {'timestamp': pd.date_range('2024-01-01', periods=10, freq='1min'),
        'voltage': [3.2, 3.21, np.nan, 3.23, 3.24, np.nan, 3.26, 3.27, 3.28, 3.29]}
df = pd.DataFrame(data)

# 线性插值
df['voltage_interpolated'] = df['voltage'].interpolate(method='linear')
print(df)

1.2 异常值检测与修正——别让“野点”带偏了方向

异常值,说白了就是数据里的“刺头”。储能系统里最常见的异常值有两种:一种是传感器故障导致的“毛刺”,比如电压突然跳到100V;另一种是真实事件,比如电池热失控前的电压骤降。

怎么区分?我个人习惯用“3σ原则”先筛一遍,再用业务逻辑去验证。

  • 3σ原则:数据在均值±3倍标准差之外的,视为异常。适合正态分布的数据。
  • IQR方法:四分位距法。数据在Q1-1.5*IQR到Q3+1.5*IQR之外的,视为异常。适合偏态分布。
  • 孤立森林:机器学习方法。适合高维数据,比如同时分析电压、电流、温度。

修正方法:

  • 如果是传感器毛刺:直接删除或用前后均值替换。
  • 如果是真实事件:保留,但打上标签,后续做故障分析用。

注意:我曾经犯过一个错——把电池的“脉冲放电”数据当成了异常值给删了。结果模型训练出来,对脉冲工况的预测完全不准。所以,一定要先问运维人员:“这个数据是不是正常的?”

# Python示例:3σ原则检测异常值
import numpy as np

# 模拟电池温度数据
temperatures = [25, 26, 25.5, 27, 100, 25.8, 26.2, 25.3, 26.5, 25.9]
mean = np.mean(temperatures)
std = np.std(temperatures)

# 检测异常
anomalies = [t for t in temperatures if abs(t - mean) > 3 * std]
print(f"异常值: {anomalies}")

1.3 数据标准化与归一化——让不同量纲的数据“说同一种语言”

储能系统的数据,量纲五花八门:电压是伏特(V),电流是安培(A),温度是摄氏度(℃),SOC是百分比(%)。你想想看,如果直接把它们扔进模型,电压的数值(几百V)会直接把SOC(0-100)给“吃掉”。

两种常用方法:

方法 公式 适用场景 我的经验
Min-Max归一化 (x - min) / (max - min) 数据有明确边界(如SOC 0-100%) 适合神经网络,但容易受异常值影响
Z-score标准化 (x - mean) / std 数据近似正态分布(如温度) 适合线性模型,对异常值不敏感

我的习惯:如果后续要用深度学习模型,我倾向于用Min-Max归一化,把数据压到[0,1]区间。如果是传统机器学习模型(如随机森林),Z-score标准化更稳妥。

# Python示例:Min-Max归一化
from sklearn.preprocessing import MinMaxScaler
import numpy as np

# 模拟储能数据:电压、电流、温度
data = np.array([[350, 50, 25],
                 [360, 55, 26],
                 [340, 45, 24],
                 [355, 52, 25.5]])

scaler = MinMaxScaler()
normalized_data = scaler.fit_transform(data)
print(normalized_data)

1.4 时间戳对齐——让所有数据“踩在同一个节拍上”

储能系统里,不同传感器的采样频率可能不一样。比如电压传感器每1秒采一次,电流传感器每0.5秒采一次,温度传感器每10秒采一次。如果不做时间戳对齐,你根本没法做联合分析。

对齐策略:

  • 降采样:把高频数据降到低频。比如把0.5秒的电流数据,每2个点取一个均值,变成1秒一个点。
  • 升采样:把低频数据升到高频。比如把10秒的温度数据,用插值变成1秒一个点。
  • 重采样:统一到一个固定的时间频率。比如全部重采样到1秒间隔。

关键点:时间戳对齐不是简单的“对齐时间点”,而是要保证数据在时间上的“因果一致性”。比如电流变化了,电压要过几毫秒才会响应。如果你把电流和电压直接对齐到同一毫秒,反而会引入误差。

# Python示例:时间戳重采样
import pandas as pd

# 模拟不同频率的数据
voltage_data = pd.DataFrame({
    'timestamp': pd.date_range('2024-01-01', periods=10, freq='1s'),
    'voltage': [350, 351, 352, 353, 354, 355, 356, 357, 358, 359]
})

current_data = pd.DataFrame({
    'timestamp': pd.date_range('2024-01-01', periods=20, freq='0.5s'),
    'current': [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
})

# 将电流数据降采样到1秒
current_resampled = current_data.set_index('timestamp').resample('1s').mean().reset_index()
print(current_resampled)

知识体系总览

下面这张图,是我自己总结的数据清洗与预处理的核心流程。你把它打印出来贴在工位上,干活的时候瞄一眼,基本不会跑偏。

数据清洗与预处理核心流程 原始数据 缺失值处理 异常值检测与修正 标准化 / 归一化 时间戳对齐 删除 / 插值 / 填充 3σ / IQR / 孤立森林 Min-Max / Z-score 降采样 / 升采样 / 重采样

好了,这一章的内容就到这里。数据清洗与预处理,说白了就是“磨刀不误砍柴工”。你花80%的时间把数据整干净了,后面20%的分析工作就会顺风顺水。别嫌麻烦,这是每个储能数据工程师的必修课。

专注资料整理