Python pandas - 在groupby之后过滤行

jir*_*ovo 36 python lambda group-by filter pandas

例如,我有以下表格:

index,A,B
0,0,0
1,0,8
2,0,8
3,1,0
4,1,5
Run Code Online (Sandbox Code Playgroud)

分组后A:

0:
index,A,B
0,0,0
1,0,8
2,0,8

1:
index,A,B
3,1,5
4,1,3
Run Code Online (Sandbox Code Playgroud)

我需要的是从每个组中删除行,其中列中的数字B小于组列中所有行的最大值B.好吧,我有一个问题,将这个问题翻译成英文,所以这里是一个例子:

B组中列的行的最大值0:8

所以我想用指数下降一行0,并保持与行的索引12

B组中列中行的最大值1:5

所以我想删除带索引的行并使用索引4保持行3

我曾尝试使用pandas过滤功能,但问题是它一次在组中的所有行上运行:

data = <example table>
grouped = data.groupby("A")
filtered = grouped.filter(lambda x: x["B"] == x["B"].max())
Run Code Online (Sandbox Code Playgroud)

所以我理想需要的是一些过滤器,它遍历组中的所有行.

感谢帮助!

PS是否还有方法只删除组中的行而不返回DataFrame对象?

Pau*_*l H 42

你只需要applygroupby对象上使用.我修改了你的示例数据,使其更加清晰:

import pandas
from io import StringIO

csv = StringIO("""index,A,B
0,1,0.0
1,1,3.0
2,1,6.0
3,2,0.0
4,2,5.0
5,2,7.0""")

df = pandas.read_csv(csv, index_col='index')
groups = df.groupby(by=['A'])
print(groups.apply(lambda g: g[g['B'] == g['B'].max()]))
Run Code Online (Sandbox Code Playgroud)

哪个印刷品:

         A  B
A index      
1 2      1  6
2 4      2  7
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。我个人认为“filter”函数不会根据某些标准过滤行,这一点具有误导性。感觉就像是显而易见的行为。 (3认同)
  • @jirinovo`groupby.apply(function)`通过该函数运行每一组并连接所有结果.`g [...]`是花式/布尔索引 - 意味着它只返回内部条件为真的行.在这种情况下,条件是`g ['B'] == g ['B'].max()`,例如,列B中的值等于该组中B的最大值的所有行. (2认同)

Joe*_*ron 18

编辑:我刚刚使用.transformgroup by方法学习了一种更简洁的方法:

def get_max_rows(df):
    B_maxes = df.groupby('A').B.transform(max)
    return df[df.B == B_maxes] 
Run Code Online (Sandbox Code Playgroud)

B_maxes是一个与原始相同的索引系列,df包含B每个A组的最大值.您可以将许多函数传递给transform方法.我认为一旦他们输出相同长度的标量或向量.您甚至可以将一些字符串作为常用函数名称传递'median'.这与Paul H的方法略有不同,因为'A'不会是结果中的索引,但您可以轻松地将其设置为.

import numpy as np
import pandas as pd
df_lots_groups = pd.DataFrame(np.random.rand(30000, 3), columns = list('BCD')
df_lots_groups['A'] = np.random.choice(range(10000), 30000)

%timeit get_max_rows(df_lots_groups)
100 loops, best of 3: 2.86 ms per loop

%timeit df_lots_groups.groupby('A').apply(lambda df: df[ df.B == df.B.max()])
1 loops, best of 3: 5.83 s per loop
Run Code Online (Sandbox Code Playgroud)

编辑:

这是一个抽象,它允许您使用任何有效的比较运算符和任何有效的groupby方法从组中选择行:

def get_group_rows(df, group_col, condition_col, func=max, comparison='=='):
    g = df.groupby(group_col)[condition_col]
    condition_limit = g.transform(func)
    df.query('condition_col {} @condition_limit'.format(comparison))
Run Code Online (Sandbox Code Playgroud)

因此,例如,如果您希望所有行都在您调用的每个A组中的中位数B值之上

get_group_rows(df, 'A', 'B', 'median', '>')
Run Code Online (Sandbox Code Playgroud)

几个例子:

%timeit get_group_rows(df_lots_small_groups, 'A', 'B', 'max', '==')
100 loops, best of 3: 2.84 ms per loop
%timeit get_group_rows(df_lots_small_groups, 'A', 'B', 'mean', '!=')
100 loops, best of 3: 2.97 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • 我不得不减少咖啡,因为大熊猫文件如何让我的血压升高......请问你在哪里了解这件事?另外,请允许我[链接到`transform()`doc page](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.core.groupby.GroupBy.transform.html#pandas. core.groupby.GroupBy.transform) (5认同)
  • 我喜欢熊猫,但文档,错误信息和测试都有所不足.我不记得我第一次看到`transform`在哪里使用,但我很确定它就在这里.我经常通过查看问题和答案来找到解决问题的新方法.如果您使用`ipython notebook`,您可以使用制表符完成扫描各种方法,阅读文档字符串(不是很好,我知道)并只是试验它们(在这种情况下按对象创建一组并扫描其方法) (2认同)

Sur*_*rya 9

这是另一个示例:使用 idxmax() 和 .loc() 在 groupby 操作后过滤具有最大值的行

In [465]: import pandas as pd

In [466]:   df = pd.DataFrame({
               'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2'],
               'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4'], 
               'value' : [3,2,5,8,10,1]     
                })

In [467]: df
Out[467]: 
   mt   sp  value
0  S1  MM1      3
1  S1  MM1      2
2  S3  MM1      5
3  S3  MM2      8
4  S4  MM2     10
5  S4  MM2      1

### Here, idxmax() finds the indices of the rows with max value within groups,
### and .loc() filters the rows using those indices :
In [468]: df.loc[df.groupby(["mt"])["value"].idxmax()]                                                                                                                           
Out[468]: 
   mt   sp  value
0  S1  MM1      3
3  S3  MM2      8
4  S4  MM2     10
Run Code Online (Sandbox Code Playgroud)