4、缺测数据插补:四种实用方法详解
数据缺测,是测风数据清洗中最让人头疼的问题之一。我做了这么多年风资源评估,几乎每个项目都会遇到数据缺失的情况。有的缺一两个小时,有的缺好几天,甚至有的缺一整月。
缺了怎么办?直接扔掉?太浪费了。强行补上?又怕把错误数据带进去。这里我给大家介绍四种常用的插补方法,各有各的适用场景。
核心原则:插补不是编造数据,而是利用已知信息做合理估计。插补后的数据必须标注为“插补值”,不能混同于实测值。
4.1 线性插值法:最简单也最常用
线性插值,说白了就是在两个已知点之间画一条直线,然后取中间的值。这个方法我用的最多,尤其是在短时间缺测(比如缺1-2个小时)的情况下。
数学原理:
y = y₁ + (x - x₁) × (y₂ - y₁) / (x₂ - x₁)
其中 (x₁, y₁) 和 (x₂, y₂) 是缺测点前后的已知数据点。
Python实现:
import pandas as pd
import numpy as np
# 假设df是包含风速数据的DataFrame,'ws'是风速列
# 线性插补
df['ws_interpolated'] = df['ws'].interpolate(method='linear')
# 限制最大插补间隔(比如最多插补连续6个缺失值)
df['ws_interpolated'] = df['ws'].interpolate(method='linear', limit=6)
我的经验:线性插值适合缺测时间短(一般不超过3小时)的情况。我曾经在一个项目中,用线性插值补了连续12个小时的数据,结果发现插补出来的风速曲线完全不符合实际的风变化规律。后来我给自己定了个规矩:连续缺测超过6个时间点,坚决不用线性插值。
注意:线性插值假设数据在两个点之间是线性变化的。但风速变化往往是非线性的,尤其是在阵风时段。所以这个方法只适合平稳风况下的短时缺测。
4.2 邻近点插值法:简单粗暴但有效
邻近点插值,就是直接用缺测点前面(或后面)最近的有效数据来填充。这个方法听起来有点粗糙,但在某些场景下非常实用。
两种常见做法:
- 前向填充:用缺测前的最后一个有效值填充
- 后向填充:用缺测后的第一个有效值填充
# 前向填充
df['ws_ffill'] = df['ws'].fillna(method='ffill', limit=3)
# 后向填充
df['ws_bfill'] = df['ws'].fillna(method='bfill', limit=3)
我个人习惯把邻近点插值用在设备短暂停机的情况。比如测风塔因为维护停机了2个小时,这期间风速变化不大,用前一个小时的数值来补,误差其实很小。
适用场景:设备短暂故障(1-2小时)、数据采集系统重启、通讯中断等。不适合风速剧烈变化的情况。
4.3 基于相关性的插值法:风速-功率曲线法
这个方法就高级一些了。它利用风速和功率之间的物理关系来做插补。你想想看,风速和功率之间是有明确关系的——风速越大,功率越大,但不是线性关系,而是近似三次方关系。
基本原理:
- 利用已知的风速-功率数据拟合出功率曲线
- 当风速缺测时,如果有对应的功率数据,就可以反推风速
- 反过来,如果功率缺测,也可以用风速来推算功率
import numpy as np
from scipy.optimize import curve_fit
# 定义风速-功率曲线模型(标准风机功率曲线形式)
def power_curve(v, a, b, c):
return a / (1 + np.exp(-b * (v - c)))
# 拟合功率曲线
v_known = df[df['ws'].notna() & df['power'].notna()]['ws'].values
p_known = df[df['ws'].notna() & df['power'].notna()]['power'].values
params, _ = curve_fit(power_curve, v_known, p_known, p0=[2000, 0.5, 10])
# 用功率反推风速(当风速缺测但功率存在时)
def inverse_power_curve(p, a, b, c):
return c - np.log(a/p - 1) / b
mask = df['ws'].isna() & df['power'].notna()
df.loc[mask, 'ws_interpolated'] = inverse_power_curve(
df.loc[mask, 'power'].values, *params
)
避坑指南:我曾经在一个山地风电场项目中,直接用标准功率曲线做插补,结果误差很大。后来发现是因为山地风况复杂,实际功率曲线和标准曲线差异很大。所以一定要用现场实测数据来拟合曲线,不要照搬理论曲线。
4.4 时间序列插值:ARIMA模型简介
ARIMA模型,全称是自回归积分滑动平均模型。听起来很复杂,其实说白了就是利用时间序列自身的历史规律来预测缺失值。
ARIMA的三个核心参数:
| 参数 | 含义 | 通俗理解 |
|---|---|---|
| p(自回归阶数) | 用过去几个时间点的值来预测当前值 | 看过去多久的数据 |
| d(差分阶数) | 让数据变得平稳需要做几次差分 | 消除趋势和季节性 |
| q(移动平均阶数) | 用过去几个预测误差来修正当前预测 | 修正预测偏差 |
from statsmodels.tsa.arima.model import ARIMA
import warnings
warnings.filterwarnings('ignore')
# 准备数据(需要是连续的时间序列)
ts = df['ws'].dropna()
# 拟合ARIMA模型(这里用(2,1,2)作为示例)
model = ARIMA(ts, order=(2, 1, 2))
model_fit = model.fit()
# 预测缺失值(假设缺测了5个点)
forecast = model_fit.forecast(steps=5)
print("预测的5个风速值:", forecast.values)
重要提醒:ARIMA模型对数据质量要求很高。我建议至少要有200个以上的连续有效数据点才能建模。而且模型参数(p,d,q)需要通过AIC或BIC准则来选取,不能随便设。初学者可以先从简单的线性插值入手,等熟悉了再尝试ARIMA。
方法对比与选择建议
四种方法各有千秋,我给大家整理了一个对比表:
| 方法 | 适用缺测时长 | 数据要求 | 计算复杂度 | 推荐场景 |
|---|---|---|---|---|
| 线性插值 | 短时(≤3小时) | 低 | 极低 | 平稳风况、短时缺测 |
| 邻近点插值 | 极短时(≤2小时) | 低 | 极低 | 设备短暂故障 |
| 风速-功率曲线法 | 任意时长 | 需同时有风速和功率数据 | 中等 | 风电场运行数据 |
| ARIMA模型 | 短-中期(≤24小时) | 需大量历史数据 | 高 | 有长期稳定观测数据 |
我的建议:实际项目中,我通常先用线性插值处理短时缺测,再用风速-功率曲线法处理有相关数据的情况。ARIMA模型我一般用在数据质量较好的长期观测站。记住一点:插补方法越复杂,不代表结果越准确。有时候简单方法反而更可靠。
好了,四种插补方法就讲到这里。每种方法都有它的脾气,用对了地方就是好方法。我个人建议,新手先从线性插值和邻近点插值练手,等积累了一定经验再尝试风速-功率曲线法和ARIMA模型。数据插补这件事,宁可保守一点,也不要为了补数据而补出错误来。