熊猫按时间和分组滚动条件总和

Posted

技术标签:

【中文标题】熊猫按时间和分组滚动条件总和【英文标题】:Pandas rolling conditional sum on time and group 【发布时间】:2021-04-24 15:32:44 【问题描述】: 在 Python/Pandas 中,我显然有一项艰巨的任务要做。

我有一个这样的数据框:

| DATETIME | PRODUCT | AMOUNT |

我需要为每种产品(我有两个以上的产品)生成最后一列,其中包含过去 5 分钟内(假设已售出的产品)数量的累积总和。请参阅以下示例:

| DATETIME              | PRODUCT | AMOUNT | CUM SUM        |
| 2020-01-01 17:10:00   | A       | 20     | 20 -> 20       |
| 2020-01-01 17:12:00   | B       | 30     | 30 -> 30       |
| 2020-01-01 17:13:00   | A       | 10     | 20+10 -> 30    |
| 2020-01-01 17:13:00   | A       | 15     | 20+10+15 -> 45 |
| 2020-01-01 17:16:00   | B       | 10     | 30+10 -> 40    |
| 2020-01-01 17:17:00   | A       | 15     | 10+15+15 -> 40 |
| 2020-01-01 17:20:00   | B       | 20     | 10+20 -> 30    |
| 2020-01-01 17:20:00   | B       | 10     | 10+20+10 -> 40 |
| 2020-01-01 17:25:00   | A       | 10     | 10 -> 10       |

请注意,情侣(日期时间、产品)可能不是唯一的,但我仍然必须根据数据框索引保持订单。

我试过了:

    滚动功能:但不幸的是我没有固定的窗口大小,并且我没有唯一的一对(日期时间,产品)所以我不能使用日期时间作为索引然后使用.rolling('5 minutes')Groupby(product).cumsum():但我无法将总和限制在最后几分钟。

可能,我需要一些平滑且性能水平不太差的东西,才能应用于相当大的 df 。

你有什么提示吗?

提前谢谢你。

【问题讨论】:

你不能先做resample(5分钟)然后滚动吗? @DanailPetrov 谢谢,但我需要一个移动窗口,而不是固定时间步长 【参考方案1】:

您可以按时间窗口(5 分钟 == '5T')和rolling.sum 使用pd.DataFrame.groupbygroupby.applypd.DataFrame.rolling

>>> df['CUM SUM'] = (df.set_index('DATETIME')
                       .groupby('PRODUCT')
                       .apply(lambda x: x.rolling('5T').sum()
                     ).values)

             DATETIME PRODUCT  AMOUNT  CUM SUM
0 2020-01-01 17:10:00       A      20     20.0
1 2020-01-01 17:12:00       B      30     30.0
2 2020-01-01 17:13:00       A      10     30.0
3 2020-01-01 17:13:00       A      15     45.0
4 2020-01-01 17:16:00       B      10     40.0
5 2020-01-01 17:17:00       A      15     40.0
6 2020-01-01 17:20:00       B      20     30.0
7 2020-01-01 17:20:00       B      10     40.0
8 2020-01-01 17:25:00       A      10     10.0

我正在添加确切的步骤,看看你是否能发现你的 df 有什么不同:

>>> from io import StringIO
>>> df = pd.read_csv(StringIO("""
DATETIME               PRODUCT  AMOUNT
2020-01-01 17:10:00    A        20
2020-01-01 17:12:00    B        30
2020-01-01 17:13:00    A        10
2020-01-01 17:13:00    A        15
2020-01-01 17:16:00    B        10
2020-01-01 17:17:00    A        15
2020-01-01 17:20:00    B        20
2020-01-01 17:20:00    B        10
2020-01-01 17:25:00    A        10"""), sep=r'\s\s+')
>>> df['DATETIME'] = pd.to_datetime(df['DATETIME'])
>>> df

             DATETIME PRODUCT  AMOUNT
0 2020-01-01 17:10:00       A      20
1 2020-01-01 17:12:00       B      30
2 2020-01-01 17:13:00       A      10
3 2020-01-01 17:13:00       A      15
4 2020-01-01 17:16:00       B      10
5 2020-01-01 17:17:00       A      15
6 2020-01-01 17:20:00       B      20
7 2020-01-01 17:20:00       B      10
8 2020-01-01 17:25:00       A      10

>>> df['CUM SUM'] = (df.set_index('DATETIME')
                       .groupby('PRODUCT')
                       .apply(lambda x: x.rolling('5T').sum()
                     ).values)

>>> df

             DATETIME PRODUCT  AMOUNT  CUM SUM
0 2020-01-01 17:10:00       A      20     20.0
1 2020-01-01 17:12:00       B      30     30.0
2 2020-01-01 17:13:00       A      10     30.0
3 2020-01-01 17:13:00       A      15     45.0
4 2020-01-01 17:16:00       B      10     40.0
5 2020-01-01 17:17:00       A      15     40.0
6 2020-01-01 17:20:00       B      20     30.0
7 2020-01-01 17:20:00       B      10     40.0
8 2020-01-01 17:25:00       A      10     10.0

我注意到我错过了值后的右括号,已修复。

编辑

这适用于pandas 1.2.0,适用于`pandas 1.0.5':

>>> df['CUM SUM'] = (df.set_index('DATETIME')
                       .groupby('AMOUNT')
                       .apply(lambda x: x.rolling('5T').sum().reset_index(drop=True))
                       .values)

【讨论】:

我想这与我需要的非常接近,但是会出现“ValueError: cannot reindex from a duplicate axis” 我猜在您的原始数据框中,您的索引已经设置为DATETIME,在这种情况下,您不需要最后的.values 部分,也不需要.set_index('DATETIME') 部分。 不,DATETIME 只是一列。我也尝试了我的示例数据框,它出现了同样的错误(在.values 之前推断出一个括号) 您是否尝试仅在右侧运行?我的意思是没有将值分配到数据框中?如果是这样,那也会出错吗? 最后一个(对于1.0.5)与行不正确匹配,因为右侧按PRODUCT 分组,并且在重置索引后它仍然分组。无论如何,在更新到1.2.0 之后,您提出的第一个似乎终于奏效了!谢谢!

以上是关于熊猫按时间和分组滚动条件总和的主要内容,如果未能解决你的问题,请参考以下文章

相邻行熊猫的分组条件总和

如何在熊猫中按对象分组应用滚动功能

大熊猫中分组的条件比率

熊猫滚动总和分别乘以值

大熊猫分组并总和显示值

熊猫结合了滚动和重采样