熊猫每月滚动操作

时间:2017-04-22 07:06:59

标签: python pandas

我在写出这个问题的时候最终搞清楚了,所以我会发帖并回答我自己的问题以防其他人需要一些帮助。

问题

假设我们有DataFramedf,其中包含此数据。

import pandas as pd
from io import StringIO

data = StringIO(
"""\
date          spendings  category
2014-03-25    10         A
2014-04-05    20         A
2014-04-15    10         A
2014-04-25    10         B
2014-05-05    10         B
2014-05-15    10         A
2014-05-25    10         A
"""
)

df = pd.read_csv(data,sep="\s+",parse_dates=True,index_col="date")

目标

对于每一行,将spendings一个月内的每一行相加,理想情况下使用DataFrame.rolling,因为它是一种非常干净的语法。

我尝试了什么

df = df.rolling("M").sum()

但这引发了异常

ValueError: <MonthEnd> is a non-fixed frequency

版本:pandas==0.19.2

2 个答案:

答案 0 :(得分:15)

使用"D"偏移而不是"M",并专门使用"30D" 30天或大约一个月。

df = df.rolling("30D").sum()

最初,我直觉地跳到使用"M",因为我认为它代表了一个月,但现在很明显为什么这不起作用。

答案 1 :(得分:10)

为了解决为什么你不能使用像“AS”或“Y”这样的东西,在这种情况下,“Y”偏移量不是“一年”,它实际上是引用YearEnd(http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases),因此滚动功能没有得到一个固定的窗口(例如,如果您的索引在1月1日,则获得365天的窗口,如果在12月31日,则获得1天)。

如果您不需要严格的日历月,则建议的解决方案(由30D抵消)有效。或者,您将迭代日期索引,并使用偏移切片以更精确地控制总和。

如果你必须在一行中(为了便于阅读而分开):

df['Sum'] = [
    df.loc[
        edt - pd.tseries.offsets.DateOffset(months=1):edt, 'spendings'
    ].sum() for edt in df.index
]
spendings   category    Sum
date            
2014-03-25  10  A   10
2014-04-05  20  A   30
2014-04-15  10  A   40
2014-04-25  10  B   50
2014-05-05  10  B   50
2014-05-15  10  A   40
2014-05-25  10  A   40