我想根据组中的属性有选择地删除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]}
Run Code Online (Sandbox Code Playgroud)
将自定义函数/方法应用于组(在col'A'上的组内排序,过滤元素).
>>> yourGenius(grped,'A').reset_index()
Run Code Online (Sandbox Code Playgroud)
返回数据帧:
A B C
0 2 a m
1 9 b p
2 10 c t
Run Code Online (Sandbox Code Playgroud)
也许用lambda函数或.filter()有一种紧凑的方法吗?谢谢
如果要为每个组选择一行,可以使用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
Run Code Online (Sandbox Code Playgroud)
另一种选择(由jezrael建议)在实践中对于各种各样的DataFrame来说更快
dff.sort_values(by=['A'], ascending=False).drop_duplicates('B')
Run Code Online (Sandbox Code Playgroud)
如果您希望为每个组选择多个行,则可以使用groupby/apply为每个组返回子DataFrame的函数.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
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用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
Run Code Online (Sandbox Code Playgroud)
我不认为groupby/filter会做你想做的事,因为
groupby/filter过滤整个团体.它不允许您从每个组中选择特定行.