Python 如何在pandas中通过值滚动窗口执行排除组中的当前日期?
我有一个包含ID、日期和数值的数据框。我将每个ID的数据分组,然后计算前几行的累积量,时间窗口为30天。在下面的数据框中,这是使用下面的代码完成的(实际的数据框包含多个ID和多个日期) 因此,简而言之,列SUM_AMOUNT是基于其他列创建的 代码: 数据帧:Python 如何在pandas中通过值滚动窗口执行排除组中的当前日期?,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个包含ID、日期和数值的数据框。我将每个ID的数据分组,然后计算前几行的累积量,时间窗口为30天。在下面的数据框中,这是使用下面的代码完成的(实际的数据框包含多个ID和多个日期) 因此,简而言之,列SUM_AMOUNT是基于其他列创建的 代码: 数据帧: ID DATE AMOUNT SUM_AMOUNT 111935 100000 2015-02-18 455.00
ID DATE AMOUNT SUM_AMOUNT
111935 100000 2015-02-18 455.00 NaN
111936 100000 2015-02-18 455.00 455.00
111937 100000 2015-04-02 455.00 NaN
111938 100000 2015-04-02 925.00 455.00
111939 100000 2015-04-02 2780.00 1380.00
111940 100000 2015-04-09 895.00 4160.00
111941 100000 2015-04-09 425.00 5055.00
111942 100000 2015-04-09 425.00 5480.00
111943 100000 2015-04-09 925.00 5905.00
111944 100000 2015-04-09 455.00 6830.00
111947 100000 2015-05-21 1003.00 NaN
111945 100000 2015-05-26 455.00 1003.00
111946 100000 2015-05-26 925.00 1458.00
111948 100000 2015-05-26 455.00 2383.00
111949 100000 2015-05-26 2780.00 2838.00
111950 100000 2015-05-26 425.00 5618.00
111951 100000 2015-05-26 1000.00 6043.00
111952 100000 2015-05-26 455.00 7043.00
111953 100000 2015-05-26 455.00 7498.00
111954 100000 2015-06-19 925.00 7953.00
111955 100000 2015-06-19 1820.00 8878.00
111956 100000 2015-06-19 925.00 10698.00
如您所见,每个ID都有具有相同日期的行。我无法得到更详细的日期。我不想在计算中考虑相同日期的值,因为如果它们在同一日期,并且顺序很重要,我不知道它们的顺序是什么
我真正想要的
我希望能够获得过去30天内所有数据点的累计总和,不包括当前行的日期。
我已更改数据框以反映我想要的:
ID DATE AMOUNT SUM_AMOUNT
111935 100000 2015-02-18 455.00 NaN
111936 100000 2015-02-18 455.00 NaN
111937 100000 2015-04-02 455.00 NaN
111938 100000 2015-04-02 925.00 NaN
111939 100000 2015-04-02 2780.00 NaN
111940 100000 2015-04-09 895.00 4160.00
111941 100000 2015-04-09 425.00 4160.00
111942 100000 2015-04-09 425.00 4160.00
111943 100000 2015-04-09 925.00 4160.00
111944 100000 2015-04-09 455.00 4160.00
111947 100000 2015-05-21 1003.00 NaN
111945 100000 2015-05-26 455.00 1003.00
111946 100000 2015-05-26 925.00 1003.00
111948 100000 2015-05-26 455.00 1003.00
111949 100000 2015-05-26 2780.00 1003.00
111950 100000 2015-05-26 425.00 1003.00
111951 100000 2015-05-26 1000.00 1003.00
111952 100000 2015-05-26 455.00 1003.00
111953 100000 2015-05-26 455.00 1003.00
111954 100000 2015-06-19 925.00 7953.00
111955 100000 2015-06-19 1820.00 7953.00
111956 100000 2015-06-19 925.00 7953.00
因此,如果行的日期为2015-06-19,我希望在30天的窗口中包含所有先前行的总和,但日期为2015-06-19的行不应包含在该窗口中
另一个需要提及的重要事项是,我不能将行折叠成每个ID和日期一行
如何执行此操作?您可以迭代df的行,并每次定义一个新掩码:
df = pd.DataFrame({'Date' : ["2015-02-18", "2015-02-18", "2015-04-02", "2015-04-02", "2015-04-02", "2015-04-09"],
'Amount' : [455, 455, 455, 925, 2780, 895]})
Date Amount
0 2015-02-18 455
1 2015-02-18 455
2 2015-04-02 455
3 2015-04-02 925
4 2015-04-02 2780
5 2015-04-09 895
# We make sure our type is date
df['Date'] = pd.to_datetime(df['Date'], format='%Y-%m-%d')
for index, row in df.iterrows():
# We look on previous rows with dates within 30 days of our own
mask = (df['Date'] <= row['Date']) & (df['Date'] >= row['Date'] - timedelta(days=30)) & (df.index<index)
df.loc[index, 'sum'] = df.loc[mask,'Amount'].sum()
在您的预期产出中,您在合计金额时,不一致地采用或忽略同一天。我包含了它们,但您可以通过将遮罩更改为:
# There is no need for the index condition either so we remove it
mask = (df['Date'] >= row['Date'] - timedelta(days=30))
由于同一天有多个值,我想说的是,您应该首先每天获取
总和
,然后在日期之前的最后30个值上使用to not include today。使用groupby
对每个ID执行这些操作,然后在df
中对ID和日期执行这些操作
df = df.merge( (df.groupby('ID').resample('1D', on='DATE').sum()['AMOUNT'].shift()
.rolling(30, min_periods=1).sum().fillna(0).reset_index()),
on = ['ID', 'DATE'], how='left', suffixes=('', '_SUM'))
您可以得到df
,例如:
DATE ID AMOUNT AMOUNT_SUM
0 2015-02-18 100000 455.0 0.0
1 2015-02-18 100000 455.0 0.0
2 2015-04-02 100000 455.0 0.0
3 2015-04-02 100000 925.0 0.0
4 2015-04-02 100000 2780.0 0.0
5 2015-04-09 100000 895.0 4160.0
6 2015-04-09 100000 425.0 4160.0
7 2015-04-09 100000 425.0 4160.0
8 2015-04-09 100000 925.0 4160.0
9 2015-04-09 100000 455.0 4160.0
10 2015-05-21 100000 1003.0 0.0
11 2015-05-26 100000 455.0 1003.0
12 2015-05-26 100000 925.0 1003.0
13 2015-05-26 100000 455.0 1003.0
14 2015-05-26 100000 2780.0 1003.0
15 2015-05-26 100000 425.0 1003.0
16 2015-05-26 100000 1000.0 1003.0
17 2015-05-26 100000 455.0 1003.0
18 2015-05-26 100000 455.0 1003.0
19 2015-06-19 100000 925.0 7953.0
20 2015-06-19 100000 1820.0 7953.0
21 2015-06-19 100000 925.0 7953.0
你能利用一下吗<代码>。。。我不能将行折叠为每个ID和日期一行。-为什么?IIUC,索引为111938和111937的行应该是
NaN
,不是吗?@Ben.T你说得对,已经修复了这个问题。@wwii为了将来的处理,我需要将每一行分开。谢谢,这是我需要的开箱即用的想法。工作起来很有魅力。
df = df.merge( (df.groupby('ID').resample('1D', on='DATE').sum()['AMOUNT'].shift()
.rolling(30, min_periods=1).sum().fillna(0).reset_index()),
on = ['ID', 'DATE'], how='left', suffixes=('', '_SUM'))
DATE ID AMOUNT AMOUNT_SUM
0 2015-02-18 100000 455.0 0.0
1 2015-02-18 100000 455.0 0.0
2 2015-04-02 100000 455.0 0.0
3 2015-04-02 100000 925.0 0.0
4 2015-04-02 100000 2780.0 0.0
5 2015-04-09 100000 895.0 4160.0
6 2015-04-09 100000 425.0 4160.0
7 2015-04-09 100000 425.0 4160.0
8 2015-04-09 100000 925.0 4160.0
9 2015-04-09 100000 455.0 4160.0
10 2015-05-21 100000 1003.0 0.0
11 2015-05-26 100000 455.0 1003.0
12 2015-05-26 100000 925.0 1003.0
13 2015-05-26 100000 455.0 1003.0
14 2015-05-26 100000 2780.0 1003.0
15 2015-05-26 100000 425.0 1003.0
16 2015-05-26 100000 1000.0 1003.0
17 2015-05-26 100000 455.0 1003.0
18 2015-05-26 100000 455.0 1003.0
19 2015-06-19 100000 925.0 7953.0
20 2015-06-19 100000 1820.0 7953.0
21 2015-06-19 100000 925.0 7953.0