如何实现基于新时间戳的Pandas时间序列插值函数?
如何优雅实现基于新时间索引的Pandas插值函数?
我需要实现一个函数:
pandas_interpolate(df: pd.DataFrame, newTime: pd.DatetimeIndex, method: str = 'linear') -> pd.DataFrame
该函数接收带有DatetimeIndex索引的现有DataFrame,返回以newTime为索引的新DataFrame。新DataFrame的每列值需通过对原DataFrame的值插值得到,功能类似numpy.interp。
我了解pandas.DataFrame.interpolate方法,但它仅对现有NaN值插值,无法接收新索引作为参数。
目前我有两种思路:
- 将新索引追加到DataFrame末尾并设对应值为NaN,删除重复索引后调用pandas插值方法,再筛选新索引对应的行;
- 将DataFrame转为numpy数组,遍历列使用numpy插值后转回DataFrame。
这两种方法虽可行但不够优雅,请问是否有官方推荐的实现方式?
补充示例
df = pd.DataFrame({'value': [1, 2, 3]}, index=pd.DatetimeIndex(['2024-01-01', '2024-01-15', '2024-01-30'])) newTime = pd.date_range(start=df.index[0], end=df.index[-1], freq='1D')
生成的newTime为:
DatetimeIndex(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-06', '2024-01-07', '2024-01-08', '2024-01-09', '2024-01-10', '2024-01-11', '2024-01-12', '2024-01-13', '2024-01-14', '2024-01-15', '2024-01-16', '2024-01-17', '2024-01-18', '2024-01-19', '2024-01-20', '2024-01-21', '2024-01-22', '2024-01-23', '2024-01-24', '2024-01-25', '2024-01-26', '2024-01-27', '2024-01-28', '2024-01-29', '2024-01-30'], dtype='datetime64[ns]', freq='D')
函数的预期输出如下(手动实现示例):
pd.DataFrame({'value': np.interp(np.arange(1, 31), [1,15,30], [1,2,3])}, index=newTime)
具体输出为:
value 2024-01-01 1.000000 2024-01-02 1.071429 2024-01-03 1.142857 2024-01-04 1.214286 2024-01-05 1.285714 2024-01-06 1.357143 2024-01-07 1.428571 2024-01-08 1.500000 2024-01-09 1.571429 2024-01-10 1.642857 2024-01-11 1.714286 2024-01-12 1.785714 2024-01-13 1.857143 2024-01-14 1.928571 2024-01-15 2.000000 2024-01-16 2.066667 2024-01-17 2.133333 2024-01-18 2.200000 2024-01-19 2.266667 2024-01-20 2.333333 2024-01-21 2.400000 2024-01-22 2.466667 2024-01-23 2.533333 2024-01-24 2.600000 2024-01-25 2.666667 2024-01-26 2.733333 2024-01-27 2.800000 2024-01-28 2.866667 2024-01-29 2.933333 2024-01-30 3.000000
重要说明
原始数据的时间精度可能与新时间戳不同(如原始为小时级),可能不存在与新索引匹配的时间点。
官方推荐实现方式
Pandas官方更优雅的实现是结合reindex和interpolate方法,直接将原数据对齐到新时间索引后完成插值:
方法1:结合reindex与interpolate
def pandas_interpolate(df: pd.DataFrame, newTime: pd.DatetimeIndex, method: str = 'linear') -> pd.DataFrame: # 先合并原索引与新索引,避免遗漏原数据点,再插值,最后筛选新索引 return df.reindex(df.index.union(newTime)).interpolate(method=method).reindex(newTime)
方法2:直接对新索引索引后插值
如果新索引完全覆盖在原数据的时间范围内,也可以直接通过loc对齐新索引,再插值:
def pandas_interpolate(df: pd.DataFrame, newTime: pd.DatetimeIndex, method: str = 'linear') -> pd.DataFrame: # 对齐新索引自动生成NaN,再插值;limit_direction处理边界外插 return df.loc[newTime].interpolate(method=method, limit_direction='both')
针对时间序列优化的插值方法
对于时间索引的场景,推荐使用method='time',该方法会根据时间间隔的长短自动调整插值权重,比普通线性插值更贴合时间序列的特性:
def pandas_interpolate(df: pd.DataFrame, newTime: pd.DatetimeIndex, method: str = 'time') -> pd.DataFrame: return df.reindex(newTime).interpolate(method=method)
内容的提问来源于stack exchange,提问作者Aleksejs Fomins
相关产品推荐
相关产品推荐

