Pandas如何基于日期按指定时间间隔插值并对齐合并数据
实现方案
核心逻辑是先把宽表中每一组「时间列+数值列」拆分为独立的时间序列,按指定间隔生成统一时间基准轴,对每个序列做插值后合并,最终得到每行时间完全对齐的结果。
1. 通用处理函数与数据加载
先写适配两个DataFrame的通用处理逻辑,避免重复代码:
import pandas as pd import numpy as np # 加载原始数据 df = pd.read_excel("https://github.com/norhther/datasets/raw/main/ncp1b.xlsx", sheet_name="Sheet1") df2 = pd.read_excel("https://github.com/norhther/datasets/raw/main/ncp1b.xlsx", sheet_name="Sheet2") df2.dropna(inplace = True) def align_interpolate_wide_df(input_df, freq='10min'): """ 处理每2列为一组(时间列、数值列)的宽表,输出时间对齐、按指定频率插值后的结果 :param input_df: 原始宽表 :param freq: 重采样时间间隔,默认10分钟 """ series_list = [] # 按步长2遍历列,每一组对应X时间列、Y数值列 for col_idx in range(0, len(input_df.columns), 2): x_col = input_df.columns[col_idx] y_col = input_df.columns[col_idx + 1] # 提取当前测点的非空数据,格式化时间索引 metric_name = y_col.replace('Y-Axis Value ', '') if not metric_name: metric_name = 'main_metric' temp_series = ( input_df[[x_col, y_col]] .dropna() .set_index(x_col)[y_col] .rename(metric_name) ) temp_series.index = pd.to_datetime(temp_series.index) series_list.append(temp_series) # 生成覆盖所有测点时间范围的统一时间轴 global_start = min([s.index.min() for s in series_list]) global_end = max([s.index.max() for s in series_list]) unified_time_index = pd.date_range(start=global_start, end=global_end, freq=freq) # 所有序列重索引到统一时间轴,做时间加权插值后合并为宽表 aligned_df = pd.concat( [s.reindex(unified_time_index).interpolate(method='time') for s in series_list], axis=1 ) aligned_df = aligned_df.reset_index().rename(columns={'index': 'unified_timestamp'}) return aligned_df
2. 处理第一个DataFrame(df)
直接调用函数即可得到时间完全对齐的插值结果,可通过修改freq参数调整时间间隔,比如5分钟传'5min'、1小时传'1H':
df_aligned = align_interpolate_wide_df(df, freq='10min')
处理后df_aligned第一列为统一时间戳,后续每列对应一个测点的插值后数值,不存在同一行时间错位问题。
3. 处理第二个DataFrame(df2)
先完成插值对齐,再将插值结果追加到原始df2末尾即可:
df2_aligned = align_interpolate_wide_df(df2, freq='10min') # 插值结果追加到原始数据,列不对齐位置自动填充空值 df2_combined = pd.concat([df2, df2_aligned], axis=0, ignore_index=True)
补充说明
- 默认使用
time方法做时间加权线性插值,适配原始采样时间不均匀的场景,需要换插值方式(比如前值填充ffill、三次样条spline)直接修改interpolate的method参数即可。 - 统一时间轴默认取所有测点的最早、最晚时间作为起止,需要自定义时间范围直接替换
global_start、global_end的取值即可。 - 结果列默认提取测点编号作为列名,需要保留原始Y轴列名可删掉函数内的
metric_name重命名逻辑。
内容的提问来源于stack exchange,提问作者Norhther
相关产品推荐
相关产品推荐

