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
假设我们有这样的数据框
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