如何有选择地过滤pandas组中的元素

Zig*_*ien 2 pandas

我想根据组中的属性有选择地删除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()有一种紧凑的方法吗?谢谢

unu*_*tbu 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
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过滤整个团体.它不允许您从每个组中选择特定行.