【问题标题】:Pandas monthly rolling operation熊猫包月滚动操作
【发布时间】:2017-09-19 06:16:02
【问题描述】:

我最终在写这个问题时弄明白了,所以我还是会发布并回答我自己的问题,以防其他人需要一点帮助。

问题

假设我们有一个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

【问题讨论】:

    标签: python pandas


    【解决方案1】:

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

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

    最初,我凭直觉跳到使用 "M",因为我认为它代表一个月,但现在很清楚为什么它不起作用。

    【讨论】:

    • 注意:我有一段时间没看这个了。滚动窗口必须有固定的宽度——“一个月”不是固定的天数。考虑上面给出的滚动操作是如何工作的:对于每一行,取周围 30 天内的行并将它们相加。如果相反:对于每一行,取“一个月”内的周围行并将它们相加,算法将如何确定该月的长度? 28天? 30天? 31 天?
    • 好像是这样。我不认为一周总是7天。根据所使用的日历系统,有时一年中的最后一周不完全是 7 天,或者一年中的第一周不是。我不确定这一点,只记得不久前在某个地方读过这个。
    • @FilipKilibarda “取周围 30 天内的行”是指当前行日期前 30 天内和当前行日期前 30 天吗?
    • @derNincompoop 否。窗口大小为 30 天。您可以使用 center=True 参数将滚动窗口居中,使其占用当前行的 +-15 天。此处的文档中对此进行了描述:pandas.pydata.org/pandas-docs/stable/generated/…
    • 如果您使用pandas.Grouper 进行选择,则通过“M”选择实际上有效。查看此堆栈:stackoverflow.com/a/42256129/1445572
    【解决方案2】:

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

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

    如果你必须在一行中完成(为了可读性而分开):

    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
    

    【讨论】:

    • 这个方法其实很慢,不然很好回答。我正在寻找一种矢量化方法。 (我的 ~1.5K 行的单个 df 需要 ~1s,我有 ~25K dfs 来处理!)
    猜你喜欢
    • 2020-04-21
    • 2018-07-30
    • 1970-01-01
    • 2018-06-26
    • 2017-03-30
    • 2019-04-11
    • 1970-01-01
    • 2017-12-28
    • 2016-11-03
    相关资源
    最近更新 更多