我想根据组中的属性有选择地删除pandas组的元素。
以下是一个示例:删除除“A”列中值最高的行之外的所有元素
>>> dff = pd.DataFrame({'A': np.arange(8), 'B': list('aabbbbcc'), 'C': list('lmnopqrt')})
>>> dff
A B C
0 0 a l
1 2 a m
2 4 b n
3 1 b o
4 9 b p
5 2 b q
6 3 c r
7 10 c t
>>> grped = dff.groupby('B')
>>> grped.groups
{'a': [0, 1], 'c': [6, 7], 'b': [2, 3, 4, 5]}
将自定义函数/方法应用于组(在col'A'组中排序,过滤元素)。
>>> yourGenius(grped,'A').reset_index()
返回dataframe:
A B C
0 2 a m
1 9 b p
2 10 c t
使用lambda函数或.filter()可能有一种紧凑的方法吗?谢谢
答案 0 :(得分:6)
如果您想为每个组选择一行,可以使用groupby/agg
返回索引值并使用loc
选择行。
例如,要按B
分组,然后选择A
值最高的行:
In [171]: dff
Out[171]:
A B C
0 0 a l
1 2 a m
2 4 b n
3 1 b o
4 9 b p
5 2 b q
6 3 c r
7 10 c t
[8 rows x 3 columns]
In [172]: dff.loc[dff.groupby('B')['A'].idxmax()]
Out[172]:
A B C
1 2 a m
4 9 b p
7 10 c t
另一个选项(suggested by jezrael),实际上是faster for a wide range of DataFrames
dff.sort_values(by=['A'], ascending=False).drop_duplicates('B')
如果您希望为每个组选择多行,可以将groupby/apply
与返回子数据框架的函数一起使用
每组。然后,apply
会尝试为您合并这些子DataFrame。
例如,要从每个组中选择除最后一行之外的所有行:
In [216]: df = pd.DataFrame(np.arange(15).reshape(5,3), columns=list('ABC'), index=list('vwxyz')); df['A'] %= 2; df
Out[216]:
A B C
v 0 1 2
w 1 4 5
x 0 7 8
y 1 10 11
z 0 13 14
In [217]: df.groupby(['A']).apply(lambda grp: grp.iloc[:-1]).reset_index(drop=True, level=0)
Out[217]:
A B C
v 0 1 2
x 0 7 8
w 1 4 5
另一种方法是使用groupby/apply
返回一系列索引值。再次apply
将尝试将该系列加入一个系列。然后,您可以使用df.loc
按索引值选择行:
In [218]: df.loc[df.groupby(['A']).apply(lambda grp: pd.Series(grp.index[:-1]))]
Out[218]:
A B C
v 0 1 2
x 0 7 8
w 1 4 5
我不认为groupby/filter
会做你想做的事,因为
groupby/filter
过滤整个群组。它不允许您从每个组中选择特定行。