pandas.resample(或 groupby)的自定义间隔

Custom intervals for pandas.resample (or groupby)

假设我从这个数据框开始

d = {'price': [10, 12, 8, 12, 14, 18, 10, 20],
     'volume': [50, 60, 40, 100, 50, 100, 40, 50]}
df = pd.DataFrame(d)
df['a_date'] = pd.date_range('01/01/2018',
                             periods=8,
                             freq='W')

df
    price   volume  a_date
0   10      50      2018-01-07
1   12      60      2018-01-14
2   8       40      2018-01-21
3   12      100     2018-01-28
4   14      50      2018-02-04
5   18      100     2018-02-11
6   10      40      2018-02-18
7   20      50      2018-02-25

现在,我想 resample/groupby 以大约 10 天的时间间隔聚合数据,但具有预定义的开始和结束日期,即 10 日和 20 日和该月的最后一天,例如:

2018-01-01 to 2018-01-10
2018-01-11 to 2018-01-20
2018-01-21 to 2018-01-31
2018-02-01 to 2018-02-10
2018-02-11 to 2018-02-20
2018-02-21 to 2018-02-28

如果跨区间求和,结果将是:

             price  volume  
a_date
2018-01-10   10     50      
2018-01-20   12     60      
2018-01-31   20     140     
2018-02-10   14     50      
2018-02-20   28     140     
2018-02-28   20     50      

我能做到的最接近的是 df.resample('10D', on='a_date').sum() 但显然我需要一些更自定义的间隔。 我很乐意只传递一组间隔,但我认为这是不可能的。

我试过,作为一个实验:

td = pd.to_datetime('2018-01-10') - pd.to_datetime('2018-01-01')
df.resample(td, on='a_date').sum()

pandas.Timedelta 不保留有关特定日期的信息。

编辑:

用于测试该月第一天的不同数据框:

d = {'price': np.arange(20)+1,
    'volume': np.arange(20)+5}
df = pd.DataFrame(d)
df['a_date'] = pd.date_range('01/01/2018',
                             periods=20,
                             freq='D')

应用已接受的答案给出(不考虑第一天):

      a_date  price  volume
0 2018-01-10     54      90
1 2018-01-20    155     195

与(第一个时间间隔 2018-01-01 至 2018-01-10)比较:

df.iloc[:10].sum()

price     55
volume    95
dtype: int64

尝试:

from pandas.tseries.offsets import MonthEnd

bins = []
end = df["a_date"].max()
current = df["a_date"].min()
current = pd.Timestamp(year=current.year, month=current.month, day=1)
while True:
    bins.append(current)
    bins.append(current + pd.Timedelta(days=9))
    bins.append(current + pd.Timedelta(days=19))
    bins.append(current + MonthEnd())
    if bins[-1] > end:
        break
    current = bins[-1] + pd.Timedelta(days=1)

x = (df.groupby(pd.cut(df["a_date"], bins)).sum()).reset_index()
x["a_date"] = x["a_date"].cat.categories.right
print(x[~(x.price.eq(0) & x.volume.eq(0))])

打印:

      a_date  price  volume
0 2018-01-10     10      50
1 2018-01-20     12      60
2 2018-01-31     20     140
4 2018-02-10     14      50
5 2018-02-20     28     140
6 2018-02-28     20      50

编辑:调整后的箱子:

from pandas.tseries.offsets import MonthEnd

end = df["a_date"].max()
current = df["a_date"].min()
bins = [
    pd.Timestamp(year=current.year, month=current.month, day=1) - MonthEnd(),
]
current = bins[-1]
while True:
    bins.append(bins[-1] + pd.Timedelta(days=10))
    bins.append(bins[-1] + pd.Timedelta(days=10))
    bins.append(current + MonthEnd())
    if bins[-1] > end:
        break
    current = bins[-1]

x = (df.groupby(pd.cut(df["a_date"], bins)).sum()).reset_index()
x["a_date"] = x["a_date"].cat.categories.right
print(x[~(x.price.eq(0) & x.volume.eq(0))])

打印:

      a_date  price  volume
0 2018-01-10     55      95
1 2018-01-20    155     195