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

时间:2014-04-12 02:08:39

标签: 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]}

将自定义函数/方法应用于组(在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()可能有一种紧凑的方法吗?谢谢

1 个答案:

答案 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过滤整个群组。它不允许您从每个组中选择特定行。