如何在pandas中通过值滚动窗口执行排除组中的当前日期?

2024-04-25 20:01:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含ID、日期和数值的数据框。我将每个ID的数据分组,然后计算前几行的累计量,时间窗口为30天。在下面的数据帧中,这是使用下面的代码实现的(实际数据帧包含多个ID和多个日期)。在

简而言之,SUM_AMOUNT列是基于其他列创建的。在

代码:

def get_rolling_amount(grp, freq, on_name, column_name):
    return grp.rolling(freq, on=on_name, closed='left')[column_name].sum()

df[new_column_name] = df.groupby('ID', as_index=False, group_keys=False)\
                         .apply(get_rolling_amount, '30D', 'DATE', 'AMOUNT')

数据帧:

^{pr2}$

如您所见,每个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和日期生成一行。在

我该怎么做?在


Tags: 数据代码nameiddfgetoncolumn
2条回答

因为同一天有多个值,所以我建议您首先^{}daily来获得sum每天,然后使用^{}不包括今天的日期之前的最后30个值。使用groupby对每个ID执行这些操作,然后对ID执行^{},并将日期追溯到df。在

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例如:

^{pr2}$

您可以迭代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()

输出:

^{pr2}$

在你的预期产出中,你在合计金额时不一致地采取或忽略同一天。我包括了它们,但你可以忽略它们,方法是将遮罩改为:

^{3}$

相关问题 更多 >