我正在尝试建立一个时间段,在这种情况下,假设是30天,在此期间,每个ID和Project的金额都会被添加。
基本上,30天总和的开始日期必须是在开始日期之前首次看到ID和项目的时间。然后,如果在30天之内再次看到相同的ID和项目,则应将其与前一个一起添加。 30天后,如果出现相同的ID和项目,则应再启动一个SUM(),并再使用30天。
经过大量的质量检查和协助,我遇到了一个我无法解决的错误-我将不胜感激任何人的时间,并请您提供解决方案。
输入数据帧为:
ID Project Amount Start Date
2345 251 3 3/20/17
3456 251 50 4/10/17
1234 203 75 4/12/17
1234 203 100 4/13/17
2345 251 4 4/16/17
3456 251 125 4/28/17
3456 251 300 4/28/17
3456 251 50 3/22/18
3456 251 100 3/23/18
1234 203 1 5/29/18
1234 203 2 5/29/18
1234 203 29.65 5/29/18
3456 251 43.75 6/5/18
预期输出:
ID Project Period Amount
1234 203 0 175
1234 203 9 32.65
2345 251 0 7
3456 251 0 475
3456 251 7 150
3456 251 9 43.75
实际输出:
ID Project Period Amount
1234 203 0 175
1234 203 9 32.65
2345 251 0 7
3456 251 0 50
3456 251 5 425
3456 251 7 150
3456 251 9 43.75
如您所见,425和50由于某种原因未加在一起。实际应该显示475,分别是4/10/17的50,4/28/17的125和4/28/17的300。
我也尝试过通过Project也进行“ sort_values”操作,但这没有用。再次感谢任何帮助,谢谢!
答案 0 :(得分:1)
您基本上正在看一个孤岛问题。对于具有相同ID
和Project
的行,一个“岛”跨越30天。 Start Date
在此期间落入的任何行都被分组到同一岛。否则,他们将开始一个新的“岛屿”。
def summarize(x):
date = x['Start Date'].iloc[0]
islands = [date]
gap = pd.Timedelta(days=30)
for d in x['Start Date'].iloc[1:]:
date = d if (d - date) > gap else date
islands.append(date)
return x.groupby(islands).agg({
'Amount': 'sum'
})
df.sort_values('Start Date').groupby(['ID', 'Project']).apply(summarize)
输出:
Amount
ID Project
1234 201 2018-07-16 100.00
203 2017-04-13 200.00
2018-05-29 81.65
2018-07-01 645.34
2345 203 2018-08-13 95.12
2019-04-12 10.00
251 2017-04-11 7.00
3456 251 2018-03-23 150.00
2018-06-05 43.75