SUM 基于"项目"和"ID"的两列



目前,我正在寻找基于ID和项目的开始日期的每个项目类型(又名分组)的单个ID的30天SUM()。这应该在每次出现相同的 ID 和项目代码时重复。我知道查询可以帮助我按 ID 和项目获取每月 SUM,但每月总和并不能回答我的问题。

下面是一个示例数据集:

ID  Project Amount  Start Date
1234    203 29.65   5/29/18
1234    203 2       6/24/18
1234    203 345.34  7/12/18
1234    201 100     7/16/18
1234    203 200     7/16/18
2345    251 3       4/11/17
2345    251 4       4/16/17
2345    203 95.12   8/13/18
2345    203 10      4/12/19
3456    251 50      3/23/18
3456    251 100     3/23/18
3456    251 43.75   6/5/18

过去,我尝试过一个基本的查询,它给了我一个分组的ID和项目,以及每月的SUM()。然而,每月进行总和并不能回答我的问题。我希望 30 天的时间范围从首次看到 ID 和项目时开始。

这是我用于每月总和的示例代码。

df.groupby(['ID', 'Project', pd.Grouper(key='Date', freq='M')])['Amount'].sum()
ID  Project Amount  Start Date  New Sum
1234    203 29.65   5/29/18     Blank
1234    203 2       6/24/18     31.65
1234    203 345.34  7/12/18     Blank
1234    201 100     7/16/18     100
1234    203 200     7/16/18     545.34
2345    251 3       4/11/17     Blank
2345    251 4       4/16/17     7
2345    203 95.12   8/13/18     95.12
2345    203 10      4/12/19     10
3456    251 50      3/23/18     Blank
3456    251 100     3/23/18     150
3456    251 43.75   6/5/18      43.75

理想的解决方案是使用:

import pandas as pd
import numpy as np
df = pd.read_csv('something.csv')
df['Start Date'] = pd.to_datetime(df['Start Date'], infer_datetime_format=True)
df = df.sort_values(by='Start Date')
new_df1 = (df.groupby(['ID', 'Project', pd.Grouper(key='Start Date', freq='M')]).agg({'Amount':'sum'}))
print(new_df1)

这为您提供:

ID   Project Start Date        
1234 201     2018-07-31  100.00
203     2017-04-30  200.00
2018-05-31   29.65
2018-06-30   52.00
2018-07-31  645.34
2345 203     2018-08-31   95.12
2019-04-30   10.00
251     2017-04-30    7.00
3456 251     2018-03-31  150.00
2018-06-30   43.75

但是,这与您的值有点不同,因为您要添加到 6/12/18 和 6/24/18 中的"5/29/18"值实际上并不在同一个月内 - 因此它被视为独立值。

如果要根据"开始日期"列中的日期自定义频率,解决方案是根据日期排序,使用第一个日期作为开始日期并向其添加 30,找到该范围内的所有值并为其分配一些唯一的"周期"id(我将其设置为开始值的索引), 然后找到超出范围的第一个值,并将其重新分配为 Start 并重复该过程。这是一个工作代码,它会产生你想要的输出:

import pandas as pd
import numpy as np
df = pd.read_csv('something.csv')
df['Start Date'] = pd.to_datetime(df['Start Date'], infer_datetime_format=True)
df = df.sort_values(by='Start Date')
df['Period'] = np.nan
indices = df.index.values.tolist()
start = indices[0]
for v in range(0, len(indices)):
if v == 0:
df['Period'] = start
else:
if df['Start Date'].loc[indices[v]] - df['Start Date'].loc[start] < pd.Timedelta(days=30):
df['Period'].loc[indices[v]] = start
else:
df['Period'].loc[indices[v]] = indices[v] 
start = indices[v]
new_df = (df.groupby(['ID', 'Project', 'Period']).agg({'Amount':'sum'}))
print(new_df)

输出:

ID   Project Period        
1234 201     6       100.00
203     3        81.65
6       645.34
11      200.00
2345 203     9        95.12
10       10.00
251     11        7.00
3456 251     3        43.75
13      150.00

最新更新