我在写出这个问题的时候最终搞清楚了,所以我会发帖并回答我自己的问题以防其他人需要一些帮助。
假设我们有DataFrame
,df
,其中包含此数据。
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
答案 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