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 基于相关性的插值法:风速-功率曲线法

这个方法就高级一些了。它利用风速和功率之间的物理关系来做插补。你想想看,风速和功率之间是有明确关系的——风速越大,功率越大,但不是线性关系,而是近似三次方关系。

基本原理:

  1. 利用已知的风速-功率数据拟合出功率曲线
  2. 当风速缺测时,如果有对应的功率数据,就可以反推风速
  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模型我一般用在数据质量较好的长期观测站。记住一点:插补方法越复杂,不代表结果越准确。有时候简单方法反而更可靠。

缺测数据插补方法选择流程图 发现数据缺测 缺测时长? 短时(≤3h) 线性插值 或邻近点插值 中长时(>3h) 有风速-功率 相关数据? 风速-功率 曲线法 有足够历史 数据(≥200点)? ARIMA模型 标记为缺失 不进行插补 注:插补后的数据必须标注为“插补值”,不得混同于实测值 简单方法 中等复杂度 高复杂度 保守处理

好了,四种插补方法就讲到这里。每种方法都有它的脾气,用对了地方就是好方法。我个人建议,新手先从线性插值和邻近点插值练手,等积累了一定经验再尝试风速-功率曲线法和ARIMA模型。数据插补这件事,宁可保守一点,也不要为了补数据而补出错误来。