Pandas groupby 对巨大数据帧的当前行之前的日期进行变换均值

问题描述 投票:0回答:1

我有一个 Pandas 数据框,看起来像

df = pd.DataFrame([['John', 'A', '1/1/2017', '10'],
                   ['John', 'A', '2/2/2017', '15'],
                   ['John', 'A', '2/2/2017', '20'],
                   ['John', 'A', '3/3/2017', '30'],
                   ['Sue', 'B', '1/1/2017', '10'],
                   ['Sue', 'B', '2/2/2017', '15'],
                   ['Sue', 'B', '3/2/2017', '20'],
                   ['Sue', 'B', '3/3/2017', '7'],
                   ['Sue', 'B', '4/4/2017', '20']],
                  columns=['Customer', 'Group', 'Deposit_Date', 'DPD'])

我想创建一个名为

PreviousMean
的新行。此列是该客户今年迄今为止的 DPD 平均值。即包括截至但不包括与当前存款日期匹配的行的所有 DPD。如果之前不存在记录,则为 null 或 0。

所以期望的结果看起来像这样

  Customer  Group  Deposit_Date  DPD  PreviousMean
0     John      A    2017-01-01   10           NaN
1     John      A    2017-02-02   15          10.0
2     John      A    2017-02-02   20          10.0
3     John      A    2017-03-03   30          15.0
4      Sue      B    2017-01-01   10           NaN
5      Sue      B    2017-02-02   15          10.0
6      Sue      B    2017-03-02   20          12.5
7      Sue      B    2017-03-03    7          15.0
8      Sue      B    2017-04-04   20          13.0

经过对网站和互联网的一些研究,这里有一个解决方案:

df['PreviousMean'] = df.apply(
    lambda x: df[(df.Customer == x.Customer) & 
                 (df.Group == x.Group) & 
                 (df.Deposit_Date < x.Deposit_Date)].DPD.mean(), 
axis=1)

而且效果很好。然而,我的实际数据帧要大得多(约 100 万行),并且上面的代码非常慢。

我之前问过类似的问题:Pandas groupby 变换平均值与当前行之前的日期对于巨大的数据帧

除了这次 groupby 是在两列上完成的,因此解决方案不起作用,我未能尝试概括它。 有没有更好的办法呢?谢谢

python pandas dataframe group-by
1个回答
0
投票

链接的解决方案工作正常,但您必须小心添加

groupby
中的所有组,然后删除
droplevel
中的匹配级别:

df['Deposit_Date'] = pd.to_datetime(df['Deposit_Date'])

groups = ['Customer', 'Group']

df['PreviousMean'] = (df.groupby(groups)
                        .apply(lambda s: s['DPD'].expanding().mean().shift()
                                                 .mask(lambda x: s['Deposit_Date'].duplicated())
                                                 .ffill(),
                               include_groups=False)
                        .droplevel(groups)
                     )

输出:

  Customer Group Deposit_Date  DPD  PreviousMean
0     John     A   2017-01-01   10           NaN
1     John     A   2017-02-02   15          10.0
2     John     A   2017-02-02   20          10.0
3     John     A   2017-03-03   30          15.0
4      Sue     B   2017-01-01   10           NaN
5      Sue     B   2017-02-02   15          10.0
6      Sue     B   2017-03-02   20          12.5
7      Sue     B   2017-03-03    7          15.0
8      Sue     B   2017-04-04   20          13.0
© www.soinside.com 2019 - 2024. All rights reserved.