Pandas:以固定间隔计算差异,并在没有更多记录时更改为变化间隔以使用最早的记录

Pandas: Calculate difference with fixed intervals and change to varying intervals to use earliest records when no more records

我得到了一个带有月记录的DataFrame,我想计算最近一个月与前6个月的差异。但是,对于那些没有完成6个月记录的人,我可以计算与它最早记录的人的差异,如下所示。

Client       Month   CAV 
 A          2021-09   30  
 A          2021-08   20
 A          2021-07   10
 A          2021-06    5
 A          2021-05   10
 A          2021-04    5
 A          2021-03   10
 B          2021-08   50
 B          2021-07   10
 B          2021-06   30     

我用了df['CAV_diff'] = df.groupby('Client')['CAV'].diff(-5),会得到:

 Client        Month   CAV     CAV_diff  
   A          2021-09   30        25 (=30-5) 
   A          2021-08   20        10 (=20-10)
   A          2021-07   10        N/A
   A          2021-06    5        N/A
   A          2021-05   10        N/A
   A          2021-04    5        N/A
   A          2021-03   10        N/A
   B          2021-08   50        N/A
   B          2021-07   10        N/A
   B          2021-06   30        N/A

我能得到如下结果吗:

 Client        Month   CAV     CAV_diff  
   A          2021-09   30        25 (=30-5)  
   A          2021-08   20        10 (=20-10)
   A          2021-07   10        0  (=10-10)
   A          2021-06    5        -5 (=5-10)
   A          2021-05   10        0
   A          2021-04    5        -5
   A          2021-03   10        0
   B          2021-08   50        20
   B          2021-07   10        -20
   B          2021-06   30        0

您可以在 'last':

上使用 .groupby() + shift() + fillna() + transform()

此处,当 .shift() 没有值时,我们通过使用 'last' 上的 .groupby() + transform() 来获取组中的最后一个条目.fillna().

的值
 df['CAV_diff'] = df['CAV'] - df.groupby('Client')['CAV'].shift(-5).fillna(df.groupby('Client')['CAV'].transform('last'))

结果:

print(df)

  Client    Month  CAV  CAV_diff
0      A  2021-09   30      25.0
1      A  2021-08   20      10.0
2      A  2021-07   10       0.0
3      A  2021-06    5      -5.0
4      A  2021-05   10       0.0
5      A  2021-04    5      -5.0
6      A  2021-03   10       0.0
7      B  2021-08   50      20.0
8      B  2021-07   10     -20.0
9      B  2021-06   30       0.0

解释:

让我们比较 shift(-5) 有和没有 .fillna() 部分的值:

df.groupby('Client')['CAV'].shift(-5)

0     5.0
1    10.0
2     NaN
3     NaN
4     NaN
5     NaN
6     NaN
7     NaN
8     NaN
9     NaN
Name: CAV, dtype: float64

由于客户端A和客户端B的条目分别只有7行和3行,所以只有客户端A的shift(-5)的前2行有值。客户 B 没有价值。

fillna() 与客户组的最后一个条目一起,我们得到:

 df.groupby('Client')['CAV'].shift(-5).fillna(df.groupby('Client')['CAV'].transform('last'))


0     5.0
1    10.0
2    10.0
3    10.0
4    10.0
5    10.0
6    10.0
7    30.0
8    30.0
9    30.0
Name: CAV, dtype: float64

NaN 个条目用每个组中的最后一个值填充。