从 pandas DataFrame 或 Series 插值到新的 DatetimeIndex

Interpolating from a pandas DataFrame or Series to a new DatetimeIndex

假设我在 pandas 有一个每小时的系列节目,可以假设来源是常规的,但它是间隙的。如果我想将它插入到 15 分钟,pandas API 提供 resample(15min).interpolate('cubic')。它插值到新的时间并提供对插值限制的一些控制。样条曲线有助于完善系列并填补小的空白。具体来说:

tndx = pd.date_range(start="2019-01-01",end="2019-01-10",freq="H")    
tnum = np.arange(0.,len(tndx))
signal = np.cos(tnum*2.*np.pi/24.)

signal[80:85] = np.nan   # too wide a gap
signal[160:168:2] = np.nan   # these can be interpolated

df = pd.DataFrame({"signal":signal},index=tndx)    
df1= df.resample('15min').interpolate('cubic',limit=9)

现在假设我有一个不规则的日期时间索引。在下面的例子中,第一次是一个规律的时间点,第二次是在大间隙,最后是在穿插的短暂间隙。

tndx2 = pd.DatetimeIndex('2019-01-04 00:00','2019-01-04 10:17','2019-01-07 16:00')

如何从原始系列(每小时)插入到这个不规则时间系列?

构建包含原始数据和目标数据的序列是唯一的选择吗?我该怎么做?实现插值到独立的不规则索引并施加间隙限制的目标的最经济的方法是什么?

如果时间戳不规则,首先将日期时间设置为索引,然后可以使用interpolate方法index df1= df.resample('15min').interpolate('index')

您可以在此处找到更多信息https://pandas.pydata.org/pandas-docs/version/0.16.2/generated/pandas.DataFrame.interpolate.html

这是 pandas 插值 API 中的示例解决方案,它似乎无法使用源系列中的横坐标和值来插值到由目标索引,作为单独的数据结构。此方法通过将目标添加到源来解决此问题。该方法利用 df.interpolatelimit 参数,它可以使用 API 中的任何插值算法,但它并不完美,因为限制是根据值的数量和如果在 NaN 补丁中有很多目标点,那么这些目标点也会被计算在内。

tndx = pd.date_range(start="2019-01-01",end="2019-01-10",freq="H")    
tnum = np.arange(0.,len(tndx))
signal = np.cos(tnum*2.*np.pi/24.)

signal[80:85] = np.nan
signal[160:168:2] = np.nan
df = pd.DataFrame({"signal":signal},index=tndx)

# Express the destination times as a dataframe and append to the source
tndx2 = pd.DatetimeIndex(['2019-01-04 00:00','2019-01-04 10:17','2019-01-07 16:00'])
df2 = pd.DataFrame( {"signal": [np.nan,np.nan,np.nan]} , index = tndx2)
big_df = df.append(df2,sort=True)  

# At this point there are duplicates with NaN values at the bottom of the DataFrame
# representing the destination points. If these are surrounded by lots of NaNs in the source frame
# and we want the limit argument to work in the call to interpolate, the frame has to be sorted and duplicates removed.     
big_df = big_df.loc[~big_df.index.duplicated(keep='first')].sort_index(axis=0,level=0)

# Extract at destination locations
interpolated = big_df.interpolate(method='cubic',limit=3).loc[tndx2]