Python 使用自定义周期重新采样
是否有一种“食谱”方法可以对周期(半)不规则的数据帧进行重新采样 我每天都有一个数据集,希望它能重新采样到有时(在科学文献中)被称为dekad的数据集。我不认为有一个合适的英语术语来形容它,但它基本上把一个月分成三到十天,第三天是8到11天之间的剩余时间 我自己提出了两个解决方案,一个是针对这种情况的具体解决方案,另一个是针对任何不规则周期的更一般的解决方案。但两者都不是很好,所以我很好奇其他人是如何处理这种情况的 让我们从创建一些示例数据开始:Python 使用自定义周期重新采样,python,pandas,Python,Pandas,是否有一种“食谱”方法可以对周期(半)不规则的数据帧进行重新采样 我每天都有一个数据集,希望它能重新采样到有时(在科学文献中)被称为dekad的数据集。我不认为有一个合适的英语术语来形容它,但它基本上把一个月分成三到十天,第三天是8到11天之间的剩余时间 我自己提出了两个解决方案,一个是针对这种情况的具体解决方案,另一个是针对任何不规则周期的更一般的解决方案。但两者都不是很好,所以我很好奇其他人是如何处理这种情况的 让我们从创建一些示例数据开始: import pandas as pd beg
import pandas as pd
begin = pd.datetime(2013,1,1)
end = pd.datetime(2013,2,20)
dtrange = pd.date_range(begin, end)
p1 = np.random.rand(len(dtrange)) + 5
p2 = np.random.rand(len(dtrange)) + 10
df = pd.DataFrame({'p1': p1, 'p2': p2}, index=dtrange)
import pandas as pd
import numpy as np
begin = pd.datetime(2013,1,1)
end = pd.datetime(2013,2,20)
dtrange = pd.date_range(begin, end)
p1 = np.random.rand(len(dtrange)) + 5
p2 = np.random.rand(len(dtrange)) + 10
df = pd.DataFrame({'p1': p1, 'p2': p2}, index=dtrange)
我想到的第一件事是按单个月份(YYYYMM)分组,然后手动切片。比如:
def to_dec1(data, func):
# create the indexes, start of the ~10day period
idx1 = pd.datetime(data.index[0].year, data.index[0].month, 1)
idx2 = idx1 + datetime.timedelta(days=10)
idx3 = idx2 + datetime.timedelta(days=10)
# slice the period and perform function
oneday = datetime.timedelta(days=1)
fir = func(data.ix[:idx2 - oneday].values, axis=0)
sec = func(data.ix[idx2:idx3 - oneday].values, axis=0)
thi = func(data.ix[idx3:].values, axis=0)
return pd.DataFrame([fir,sec,thi], index=[idx1,idx2,idx3], columns=data.columns)
dfmean = df.groupby(lambda x: x.strftime('%Y%m'), group_keys=False).apply(to_dec1, np.mean)
其结果是:
print dfmean
p1 p2
2013-01-01 5.436778 10.409845
2013-01-11 5.534509 10.482231
2013-01-21 5.449058 10.454777
2013-02-01 5.685700 10.422697
2013-02-11 5.578137 10.532180
2013-02-21 NaN NaN
请注意,作为回报,你总是会得到整整一个月的“dekads”,这不是一个问题,如果需要的话,很容易删除
另一种解决方案的工作原理是提供一系列的日期,在这些日期,您可以分割数据帧,并对每个数据段执行一个函数。它在你想要的时间上更灵活
def to_dec2(data, dts, func):
chucks = []
for n,start in enumerate(dts[:-1]):
end = dts[n+1] - datetime.timedelta(days=1)
chucks.append(func(data.ix[start:end].values, axis=0))
return pd.DataFrame(chucks, index=dts[:-1], columns=data.columns)
dfmean2 = to_dec2(df, dfmean.index, np.mean)
请注意,我使用上一个结果的索引作为日期范围,以节省一些自己“构建”它的时间
处理这些案件的最佳方式是什么?熊猫是否有更多的内置方法 如果使用numpy 1.7,则可以使用datetime64和timedelta64数组进行计算: 创建示例数据:
import pandas as pd
begin = pd.datetime(2013,1,1)
end = pd.datetime(2013,2,20)
dtrange = pd.date_range(begin, end)
p1 = np.random.rand(len(dtrange)) + 5
p2 = np.random.rand(len(dtrange)) + 10
df = pd.DataFrame({'p1': p1, 'p2': p2}, index=dtrange)
import pandas as pd
import numpy as np
begin = pd.datetime(2013,1,1)
end = pd.datetime(2013,2,20)
dtrange = pd.date_range(begin, end)
p1 = np.random.rand(len(dtrange)) + 5
p2 = np.random.rand(len(dtrange)) + 10
df = pd.DataFrame({'p1': p1, 'p2': p2}, index=dtrange)
计算dekad的日期:
d = df.index.day - np.clip((df.index.day-1) // 10, 0, 2)*10 - 1
date = df.index.values - np.array(d, dtype="timedelta64[D]")
df.groupby(date).mean()
输出为:
p1 p2
2013-01-01 5.413795 10.445640
2013-01-11 5.516063 10.491339
2013-01-21 5.539676 10.528745
2013-02-01 5.783467 10.478001
2013-02-11 5.358787 10.579149
使用HYRY的数据和解决方案,直到计算
d
变量,我们还可以在pandas 0.11-dev或更高版本中执行以下操作(无论numpy版本如何):
日期的构造与上述类似
date = pd.Series(df.index) - pd.Series([ timedelta(int(i)) for i in d ])
df.groupby(date.values).mean()
对于更一般的情况,您可以使用[date,num_of_days]的多索引进行分组(您的例程可以方便地在任何需要的地方填充这些组),然后像正常情况一样进行分组。在任何情况下(但我必须考虑一下),使用TimeGrouper可能有一种更有效的方法来实现这一点。它在10.1中没有,我没有运行开发版本。很高兴了解未来,谢谢!