比较pandas groupby中的最后一个值

时间:2019-03-09 15:48:54

标签: python pandas pandas-groupby

这是我的数据框:

df = pd.DataFrame({'a': list('xxxxxzzz'), 'b':[0,0,1,0,1,0,1,1], 'c': [100, 101, 105, 110, 120, 125, 100, 150], 'd':[0,0,0,1,1,0,0,0]})

我将它们分组:

groups = df.groupby(['a', 'd'])

我想在df中添加另一列,以便在每组中显示c的最后一个值为b的最后一个值与b的最后一个值之间的差异(百分比)其c为1。

例如,在第一组中,我想比较第2行和第1行的groups

我想要的('x', 0) a b c d result 0 x 0 100 0 3.96 1 x 0 101 0 3.96 2 x 1 105 0 3.96 ('x', 1) a b c d result 3 x 0 110 1 9.09 4 x 1 120 1 9.09 ('z', 0) a b c d result 5 z 0 125 0 20.0 6 z 1 100 0 20.0 7 z 1 150 0 20.0 看起来像这样:

{{1}}

2 个答案:

答案 0 :(得分:1)

定义自定义函数并使用GroupBy.apply

def func(s):
    l0 = s[s.b==0].tail(1).c.item()
    l1 = s[s.b==1].tail(1).c.item()
    s['result'] = (l1 - l0)/l0 * 100
    return s

df.groupby(['a','d']).apply(func)

输出

    a   b   c   d   result
0   x   0   100 0   3.960396
1   x   0   101 0   3.960396
2   x   1   105 0   3.960396
3   x   0   110 1   9.090909
4   x   1   120 1   9.090909
5   z   0   125 0   20.000000
6   z   1   100 0   20.000000
7   z   1   150 0   20.000000

如果您分别需要每个组,只需使用列表理解[func(g) for n, g in df.groupby(['a','d'])]

答案 1 :(得分:1)

我们可以在此处执行以下操作:

  1. 应用.pct_change方法来计算每一行的变化百分比
  2. 有条件地用result填充NaN列的值
  3. 然后在fillnabfillffill上应用
# first we apply .pct_change to all rows
df['result'] = abs(round(df.groupby(['a', 'd', 'b']).c.pct_change() * 100, 2))

# after that we check if the value if b = 1 and the value of the row before = 0 and we fill in NaN if condition not true
df['result'] = np.where((df.b == 1) & (df.b.shift(1) == 0), df.result, np.NaN)

所以我们得到:

   a  b    c  d  result
0  x  0  100  0     NaN
1  x  0  101  0     NaN
2  x  1  105  0    3.96
3  x  0  110  1     NaN
4  x  1  120  1    9.09
5  z  0  125  0     NaN
6  z  1  100  0   20.00
7  z  1  150  0     NaN
# then backfill and forwardfill NaN
df.result.fillna(method='bfill', inplace=True)
df.result.fillna(method='ffill', inplace=True)

print(df)
   a  b    c  d  result
0  x  0  100  0    3.96
1  x  0  101  0    3.96
2  x  1  105  0    3.96
3  x  0  110  1    9.09
4  x  1  120  1    9.09
5  z  0  125  0   20.00
6  z  1  100  0   20.00
7  z  1  150  0   20.00