
本文介绍一种针对电力负荷时间序列数据的精细化缺失值插补方法:对每个缺失点,综合考虑当日前后各2个相邻时间点(如01:00缺失时取00:00、00:30、01:30、02:00)、以及前2天同一时刻共5个有效观测值的均值进行填充。
本文介绍一种针对电力负荷时间序列数据的精细化缺失值插补方法:对每个缺失点,综合考虑当日前后各2个相邻时间点(如01:00缺失时取00:00、00:30、01:30、02:00)、以及前2天同一时刻共5个有效观测值的均值进行填充。
在电力负荷分析中,缺失值往往具有强时空相关性——同一电表的日间模式稳定,且相邻时刻及历史同期(如同一时刻前1–2天)的读数高度相似。简单使用全局均值或线性插值会忽略这一特性,导致插补偏差。本文提出一种时空协同插补策略:对任意缺失值 df.loc[i, col](col 为时间列如 '01:00'),构造候选值集合:
- 同日邻近值:取该行所在日期(date)下,col 列前后各2个非空时间点(需确保列名按时间顺序排列);
- 历史同期值:取该行 date - pd.Timedelta('1D') 和 date - pd.Timedelta('2D') 对应行中 col 列的值(若存在且非空);
- 最终插补值:上述最多5个有效数值的算术平均值。
✅ 关键前提:时间列('00:00', '00:30', ..., '23:30')必须按升序排列,且 date 列为 datetime64 类型。
以下为完整实现代码(含健壮性处理):
import pandas as pd
import numpy as np
def impute_electricity_ts(df, time_cols=None):
"""
基于同日邻近时刻 + 前2天同期时刻的均值插补电力时序缺失值
Parameters:
-----------
df : pd.DataFrame
输入DataFrame,含 'meter IDs', 'date' 及多个时间列(如 '00:00')
time_cols : list of str, optional
时间列名列表;若为None,则自动识别除 'meter IDs' 和 'date' 外的所有列
Returns:
--------
pd.DataFrame : 插补后的DataFrame(原地修改并返回)
"""
# 确保date列为datetime类型
df = df.copy()
df['date'] = pd.to_datetime(df['date'])
# 自动识别时间列
if time_cols is None:
time_cols = [c for c in df.columns if c not in ['meter IDs', 'date']]
# 按meter ID和date排序,确保时序连续
df = df.sort_values(['meter IDs', 'date']).reset_index(drop=True)
# 构建日期索引映射:{meter_id: {date: row_idx}}
idx_map = {}
for mid, group in df.groupby('meter IDs'):
idx_map[mid] = {row['date']: idx for idx, row in group.iterrows()}
# 遍历每个时间列
for col in time_cols:
for i in range(len(df)):
if pd.isna(df.at[i, col]):
mid = df.at[i, 'meter IDs']
curr_date = df.at[i, 'date']
candidates = []
# 1. 同日邻近时刻(前后各2个)
# 获取当前行所在日期的所有时间点值(非空)
same_day_rows = df[(df['meter IDs'] == mid) & (df['date'] == curr_date)]
if not same_day_rows.empty:
# 提取所有时间列值(转为Series便于索引)
time_series = same_day_rows.iloc[0][time_cols]
col_pos = time_cols.index(col)
# 前2个:max(0, col_pos-2) 到 col_pos-1
prev_pos = max(0, col_pos - 2)
for j in range(prev_pos, col_pos):
val = time_series.iloc[j]
if pd.notna(val):
candidates.append(val)
# 后2个:col_pos+1 到 min(len-1, col_pos+2)
next_pos = min(len(time_cols), col_pos + 3)
for j in range(col_pos + 1, next_pos):
val = time_series.iloc[j]
if pd.notna(val):
candidates.append(val)
# 2. 前2天同期时刻
for offset in [1, 2]:
ref_date = curr_date - pd.Timedelta(f'{offset}D')
if ref_date in idx_map[mid]:
ref_idx = idx_map[mid][ref_date]
val = df.at[ref_idx, col]
if pd.notna(val):
candidates.append(val)
# 插补:取均值(至少1个候选值才填充,否则保持NaN)
if candidates:
df.at[i, col] = np.mean(candidates)
return df
# 使用示例
# 假设原始df已加载
# result_df = impute_electricity_ts(df)注意事项与优化建议:
- 性能提示:对大规模数据(>10万行),上述逐行循环可能较慢。可改用 groupby('meter IDs').apply() 并向量化内部逻辑,或借助 numba 加速。
- 边界处理:首日/末日缺失值无法获取前2天数据,函数自动跳过;首/末时间点(如 '00:00' 或 '23:30')缺少前后邻近值,仅使用可用部分。
- 扩展性:可通过参数 window_size=2 和 history_days=[1,2] 封装为通用接口,适配不同粒度(如15分钟)或历史窗口。
- 验证建议:插补后建议绘制某电表连续多日的热力图(seaborn.heatmap),目视检查插补值是否符合日周期规律。
该方法兼顾物理可解释性与统计稳健性,在真实电力场景中显著优于单一维度插补,是负荷数据预处理的推荐实践。

















