目前,我正在寻找基于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