【发布时间】:2014-12-23 00:56:14
【问题描述】:
我必须将我的数据集从 10 分钟间隔重新采样到 15 分钟间隔,以使其与另一个数据集同步。根据我在 stackoverflow 上的搜索,我对如何进行有一些想法,但它们都没有提供干净清晰的解决方案。
问题
问题设置
#%% Import modules
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#%% make timestamps
periods = 12
startdate = '2010-01-01'
timestamp10min = pd.date_range(startdate, freq='10Min', periods=periods)
#%% Make DataFrame and fill it with some data
df = pd.DataFrame(index=timestamp10min)
y = -(np.arange(periods)-periods/2)**2
df['y'] = y
期望的输出
现在我希望 10 分钟时的值保持不变,并且 **:15 和 **:45 的值是 **:10、**:20 和 ** 的平均值: 40,**:50。问题的核心是15分钟不是10分钟的整数倍。否则简单地应用df.resample('10Min', how='mean') 就可以了。
可能的解决方案
只需使用 15 分钟的重新采样,就可以忍受引入的小错误。
使用两种形式的重采样,
close='left', label='left'和close='right' , label='right'。之后,我可以平均两种重新采样的形式。结果会给我一些结果错误,但比第一种方法要小。将所有内容重新采样为 5 分钟数据,然后应用滚动平均值。类似的东西在这里应用:Pandas: rolling mean by time interval
使用不同数量的输入重新采样和平均:Use numpy.average with weights for resampling a pandas array 因此,我必须创建一个具有不同重量长度的新系列。权重是否应该在 1 和 2 之间交替。
将所有内容重新采样为 5 分钟数据,然后应用线性插值。该方法与方法3接近。Pandas data frame: resample with linear interpolation 编辑:@Paul H 在这些方面给出了一个可行的解决方案,它仍然可读。谢谢!
所有的方法对我来说都不是很满意。有些会导致小错误,而其他方法对于外人来说很难阅读。
实施
方法 1、2 和 5 的实现以及所需的输出。结合可视化。
#%% start plot
plt.figure()
plt.plot(df.index, df['y'], label='original')
#%% resample the data to 15 minutes and plot the result
close = 'left'; label='left'
dfresamplell = pd.DataFrame()
dfresamplell['15min'] = df.y.resample('15Min', how='mean', closed=close, label=label)
labelstring = 'close ' + close + ' label ' + label
plt.plot(dfresamplell.index, dfresamplell['15min'], label=labelstring)
close = 'right'; label='right'
dfresamplerr = pd.DataFrame()
dfresamplerr['15min'] = df.y.resample('15Min', how='mean', closed=close, label=label)
labelstring = 'close ' + close + ' label ' + label
plt.plot(dfresamplerr.index, dfresamplerr['15min'], label=labelstring)
#%% make an average
dfresampleaverage = pd.DataFrame(index=dfresamplell.index)
dfresampleaverage['15min'] = (dfresamplell['15min'].values+dfresamplerr['15min'].values[:-1])/2
plt.plot(dfresampleaverage.index, dfresampleaverage['15min'], label='average of both resampling methods')
#%% desired output
ydesired = np.zeros(periods/3*2)
i = 0
j = 0
k = 0
for val in ydesired:
if i+k==len(y): k=0
ydesired[j] = np.mean([y[i],y[i+k]])
j+=1
i+=1
if k==0: k=1;
else: k=0; i+=1
plt.plot(dfresamplell.index, ydesired, label='ydesired')
#%% suggestion of Paul H
dfreindex = df.reindex(pd.date_range(startdate, freq='5T', periods=periods*2))
dfreindex.interpolate(inplace=True)
dfreindex = dfreindex.resample('15T', how='first').head()
plt.plot(dfreindex.index, dfreindex['y'], label='method Paul H')
#%% finalize plot
plt.legend()
"""
角度的实现
作为奖励,我添加了我将用于角度插值的代码。这是通过使用复数来完成的。因为(还)没有实现复数插值,所以我将复数分成实部和虚部。平均后这些数字可以再次转换为天使。对于某些角度,这是一种比简单地平均两个角度更好的重新采样方法,例如:345 度和 5 度。 """
#%% make timestamps
periods = 24*6
startdate = '2010-01-01'
timestamp10min = pd.date_range(startdate, freq='10Min', periods=periods)
#%% Make DataFrame and fill it with some data
degrees = np.cumsum(np.random.randn(periods)*25) % 360
df = pd.DataFrame(index=timestamp10min)
df['deg'] = degrees
df['zreal'] = np.cos(df['deg']*np.pi/180)
df['zimag'] = np.sin(df['deg']*np.pi/180)
#%% suggestion of Paul H
dfreindex = df.reindex(pd.date_range(startdate, freq='5T', periods=periods*2))
dfreindex = dfreindex.interpolate()
dfresample = dfreindex.resample('15T', how='first')
#%% convert complex to degrees
def f(x):
return np.angle(x[0] + x[1]*1j, deg=True )
dfresample['degrees'] = dfresample[['zreal', 'zimag']].apply(f, axis=1)
#%% set all the values between 0-360 degrees
dfresample.loc[dfresample['degrees']<0] = 360 + dfresample.loc[dfresample['degrees']<0]
#%% wrong resampling
dfresample['deg'] = dfresample['deg'] % 360
#%% plot different sampling methods
plt.figure()
plt.plot(df.index, df['deg'], label='normal', marker='v')
plt.plot(dfresample.index, dfresample['degrees'], label='resampled according @Paul H', marker='^')
plt.plot(dfresample.index, dfresample['deg'], label='wrong resampling', marker='<')
plt.legend()
感谢您帮助我!
【问题讨论】:
-
看起来你真正想要的是更精细的插值。也许你可以通过
scipy.interpolate得到它 -
如果您将
10T数据帧重新索引(而不是重新采样)到5T,您将在例如XX:05、XX:15、...XX:55 处获得NA。那么dataframe.interpolate应该完全符合您的要求。 -
对于 OP,您确实应该避免将答案放回问题中 - 这会使后来提出问题的人非常困惑,并有损于实际的答案帖子。如果您想添加额外的有用信息,例如您的角度实现,您应该添加它作为答案!问题应该是问题,而不是答案。
标签: python numpy pandas resampling