pandas dataframe groupby 多级列的条件计数

pandas dataframe groupby conditional count on multi-level column

假设我们有这样的数据框

np.random.seed(123)
df = pd.DataFrame(np.random.randint(100,size=(4, 4)),columns = pd.MultiIndex.from_product([['exp0','exp1'],['rnd0','rnd1']],names=['experiments','rnd_runs']))

df['grp1','cat'] = ['A','A','B','B']
df['grp2','cat2'] = ['C','C','C','B']

experiments exp0            exp1            grp1 grp2
rnd_runs    rnd0    rnd1    rnd0    rnd1    cat cat2
0             66    92      98      17      A   C
1             83    57      86      97      A   C
2             96    47      73      32      B   C
3             46    96      25      83      B   B

我想 count ('exp0', 'rdn0') 列中的值与 groupby ('grp1','cat')

所以我试过了;

df['exp0_cnt','rdn0'] = df.groupby([('grp1','cat')])[('exp0', 'rdn')].apply(sum(x > 50 for x in df[(('exp0', 'rdn'))]))

但出现错误

TypeError: other must be a MultiIndex or a list of tuples

这是类似的帖子,我想我正在使用 tuples 进行多级列调用。

Better way for creating columns in a multi level columns pandas dataframe

从 groupby 中 select MultiIndex 列的唯一方法是使用 list 元组或 MultiIndex(如错误消息所示):

因此,它需要 [[('exp0', 'rdn')]] 而不是 [('exp0', 'rdn')],然后它只需要是一个有效的列名,例如 ('exp0', 'rnd0')

df['exp0_cnt', 'rdn0'] = (
    df.groupby([('grp1', 'cat')])[[('exp0', 'rnd0')]]
        #                                   ^ need to use valid column name
        #                         ^ needs to be a list of tuples
        .transform(lambda x: x.gt(50).sum())  # Some function that works
)

*我还更改了 apply 函数,因为它似乎缺少 lambda 所以我猜测了一个等效函数:

.apply(sum(x > 50 for x in df[(('exp0', 'rdn'))])

transform 因为它被分配回 DataFrame:

.transform(lambda x: x.gt(50).sum())

df:

experiments exp0      exp1      grp1 grp2 exp0_cnt
rnd_runs    rnd0 rnd1 rnd0 rnd1  cat cat2     rdn0
0             66   92   98   17    A    C        2
1             83   57   86   97    A    C        2  # 2 values over 50 (in group)
2             96   47   73   32    B    C        1
3             46   96   25   83    B    B        1  # 1 values over 50 (in group)

请注意:这意味着 SeriesGroupBy 不能通过 selecting MultiIndex 列创建,只能通过 DataFrameGroupBy 操作创建。

type(df.groupby([('grp1', 'cat')])[[('exp0', 'rnd0')]])
# <class 'pandas.core.groupby.generic.DataFrameGroupBy'>

这将排除一些操作,例如 SeriesGroupBy.unique

df.groupby([('grp1', 'cat')])[[('exp0', 'rnd0')]].unique()
AttributeError: 'DataFrameGroupBy' object has no attribute 'unique'

但是,我们可以通过从 DataFrame 中选择系列并直接按系列值分组来强制 SeriesGroupBy

df[('exp0', 'rnd0')].groupby(df[('grp1', 'cat')]).unique()
#  ^ select specific column  ^ pass the Series to groupby directly
(grp1, cat)
A    [66, 83]
B    [96, 46]
Name: (exp0, rnd0), dtype: object