在数据框中使用带条件的转换

Using transform with condition within a dataframe

有以下df

import numpy as np
import random

i = ['dog', 'cat', 'rabbit', 'elephant'] * 20

df = pd.DataFrame(np.random.randn(len(i), 3), index=i, \
            columns=list('ABC')).rename_axis('animal').reset_index()
            
df.insert(1, 'type', pd.Series(random.choice(['X', 'Y']) \
                for _ in range(len(df))))

我想要 A 列的 max,如果动物的类型是 X ... 否则 A 列的 min,在单独的列中。

将 lambda 与 group by 应用显示具有以下代码的多索引数组:

g = df.groupby(['animal', 'type'])
g.apply(lambda g: np.where (g.type == 'X', g.A.max(), g.A.min()))

有没有办法将其转换为系列,可以将其作为列添加到 df 中...比如使用 transform?

这是你想要的吗?

>>> df

     animal type     A     B     C
0       cat    Y  0.96 -0.02 -0.14
1       cat    Y -0.80  0.86  1.75
2       dog    X  1.13 -0.49 -1.66
3       dog    Y  0.84 -0.07  0.15
4  elephant    X  0.13 -0.54  0.73
5  elephant    Y  0.14  1.77  0.94
6    rabbit    X -0.12 -0.39  0.05
7    rabbit    X  0.58 -1.17  0.77

>>> def max_min_A(g):
        animal, type_ = g.name 
        return np.where(type_ == 'X', g.max(), g.min())

>>> df['new_col'] = df.groupby(['animal', 'type'])['A'].transform(max_min_A)

     animal type     A     B     C  new_col
0       cat    Y  0.96 -0.02 -0.14    -0.80
1       cat    Y -0.80  0.86  1.75    -0.80
2       dog    X  1.13 -0.49 -1.66     1.13
3       dog    Y  0.84 -0.07  0.15     0.84
4  elephant    X  0.13 -0.54  0.73     0.13
5  elephant    Y  0.14  1.77  0.94     0.14
6    rabbit    X -0.12 -0.39  0.05     0.58
7    rabbit    X  0.58 -1.17  0.77     0.58

@HarryPlotter:感谢 name 信息。很高兴看到组名作为元组传播。如果不想使用某个功能,可以使用以下方法:

df.assign(new_col=g.A.transform(lambda x: np.where(x.name[1] =='X', \
            x.max(), x.min()))) 
# x.name[1] is used to select the second element of the tuple, which is `type`