每个类别的 pandas 在某个日期范围内的总和 [英] Pandas sum over a date range for each category separately

查看:107
本文介绍了每个类别的 pandas 在某个日期范围内的总和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含不同项目销售交易时间序列的数据框:

I have a dataframe with timeseries of sales transactions for different items:

import pandas as pd
from datetime import timedelta
df_1 = pd.DataFrame()
df_2 = pd.DataFrame()
df_3 = pd.DataFrame()

# Create datetimes and data
df_1['date'] = pd.date_range('1/1/2018', periods=5, freq='D')
df_1['item'] = 1
df_1['sales']= 2

df_2['date'] = pd.date_range('1/1/2018', periods=5, freq='D')
df_2['item'] = 2
df_2['sales']= 3

df_3['date'] = pd.date_range('1/1/2018', periods=5, freq='D')
df_3['item'] = 3
df_3['sales']= 4

df = pd.concat([df_1, df_2, df_3])
df = df.sort_values(['item'])
df

结果数据框:

    date    item    sales
0   2018-01-01  1   2
1   2018-01-02  1   2
2   2018-01-03  1   2
3   2018-01-04  1   2
4   2018-01-05  1   2
0   2018-01-01  2   3
1   2018-01-02  2   3
2   2018-01-03  2   3
3   2018-01-04  2   3
4   2018-01-05  2   3
0   2018-01-01  3   4
1   2018-01-02  3   4
2   2018-01-03  3   4
3   2018-01-04  3   4
4   2018-01-05  3   4

我想计算给定时间范围内给定项目的销售额"总和.我不能用熊猫rolling.sum 因为时间序列稀疏(例如2018-01-01> 2018-01-04> 2018-01-06>等).

I want to compute a sum of "sales" for a given item in a given time window. I can't use pandas rolling.sum because the timeseries is sparse (eg. 2018-01-01 > 2018-01-04 > 2018-01-06 > etc.).

我已经尝试过此解决方案(对于时间窗口= 2天):

I've tried this solution (for time window = 2 days):

df['start_date'] = df['date'] - timedelta(3)
df['end_date'] = df['date'] - timedelta(1)
df['rolled_sales'] = df.apply(lambda x: df.loc[(df.date >= x.start_date) & 
                                            (df.date <= x.end_date), 'sales'].sum(), axis=1)

但它会得出给定时间范围内所有商品的销售总额:

but it results with sums of sales of all items for a given time window:

    date    item    sales   start_date  end_date    rolled_sales
0   2018-01-01  1   2   2017-12-29  2017-12-31  0
1   2018-01-02  1   2   2017-12-30  2018-01-01  9
2   2018-01-03  1   2   2017-12-31  2018-01-02  18
3   2018-01-04  1   2   2018-01-01  2018-01-03  27
4   2018-01-05  1   2   2018-01-02  2018-01-04  27
0   2018-01-01  2   3   2017-12-29  2017-12-31  0
1   2018-01-02  2   3   2017-12-30  2018-01-01  9
2   2018-01-03  2   3   2017-12-31  2018-01-02  18
3   2018-01-04  2   3   2018-01-01  2018-01-03  27
4   2018-01-05  2   3   2018-01-02  2018-01-04  27
0   2018-01-01  3   4   2017-12-29  2017-12-31  0
1   2018-01-02  3   4   2017-12-30  2018-01-01  9
2   2018-01-03  3   4   2017-12-31  2018-01-02  18
3   2018-01-04  3   4   2018-01-01  2018-01-03  27
4   2018-01-05  3   4   2018-01-02  2018-01-04  27

我的目标是分别为每个项目计算rolled_sales,如下所示:

My goal is to have rolled_sales computed for each item separately, like this:

    date    item    sales   start_date  end_date    rolled_sales
0   2018-01-01  1   2   2017-12-29  2017-12-31  0
1   2018-01-02  1   2   2017-12-30  2018-01-01  2
2   2018-01-03  1   2   2017-12-31  2018-01-02  4
3   2018-01-04  1   2   2018-01-01  2018-01-03  6
4   2018-01-05  1   2   2018-01-02  2018-01-04  8
0   2018-01-01  2   3   2017-12-29  2017-12-31  0
1   2018-01-02  2   3   2017-12-30  2018-01-01  3
2   2018-01-03  2   3   2017-12-31  2018-01-02  6
3   2018-01-04  2   3   2018-01-01  2018-01-03  9
4   2018-01-05  2   3   2018-01-02  2018-01-04  12
0   2018-01-01  3   4   2017-12-29  2017-12-31  0
1   2018-01-02  3   4   2017-12-30  2018-01-01  4
2   2018-01-03  3   4   2017-12-31  2018-01-02  8
3   2018-01-04  3   4   2018-01-01  2018-01-03  12
4   2018-01-05  3   4   2018-01-02  2018-01-04  16

我尝试应用此处建议的解决方案:分别为乘法值设置的熊猫滚动总和 但失败了.

I tried to apply solution suggested here: Pandas rolling sum for multiply values separately but failed.

有什么想法吗?

非常感谢:)

安迪

推荐答案

df['rolled_sum'] = (df.groupby('item')
                    .rolling('3D', on='date').sum()['sales']
                    .to_numpy()
                  )

经过一些数据处理(我删除了一些行以模拟稀疏日期,并添加了距给定日期3天的帮助程序列"start_date"和"end_date"),最终输出看起来像这样:

After some data wrangling (I removed some rows to simulate sparse dates, and added helper columns "start_date" and "end_date" for 3 days distance from a given date), the final output looks like this:

    date    item    sales   start_date  end_date    rolled_sum
0   2018-01-01  1   2   2017-12-30  2018-01-01  2.0
3   2018-01-04  1   2   2018-01-02  2018-01-04  2.0
4   2018-01-05  1   2   2018-01-03  2018-01-05  4.0
7   2018-01-08  1   2   2018-01-06  2018-01-08  2.0
9   2018-01-10  1   2   2018-01-08  2018-01-10  4.0
12  2018-01-03  2   3   2018-01-01  2018-01-03  3.0
13  2018-01-04  2   3   2018-01-02  2018-01-04  6.0
15  2018-01-06  2   3   2018-01-04  2018-01-06  6.0
17  2018-01-08  2   3   2018-01-06  2018-01-08  6.0
18  2018-01-09  2   3   2018-01-07  2018-01-09  6.0
19  2018-01-10  2   3   2018-01-08  2018-01-10  9.0
21  2018-01-02  3   4   2017-12-31  2018-01-02  4.0
23  2018-01-04  3   4   2018-01-02  2018-01-04  8.0
25  2018-01-06  3   4   2018-01-04  2018-01-06  8.0
26  2018-01-07  3   4   2018-01-05  2018-01-07  8.0
27  2018-01-08  3   4   2018-01-06  2018-01-08  12.0
28  2018-01-09  3   4   2018-01-07  2018-01-09  12.0
29  2018-01-10  3   4   2018-01-08  2018-01-10  12.0

魔术是在roll.sum参数中:我应该使用"3D"而不是"3".

The magic was in rolling.sum parameter: instead of "3", I should use "3D".

非常感谢您的帮助:)

安迪

这篇关于每个类别的 pandas 在某个日期范围内的总和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆