Python pandas - 在 groupby 之后过滤行

Posted

技术标签:

【中文标题】Python pandas - 在 groupby 之后过滤行【英文标题】:Python pandas - filter rows after groupby 【发布时间】:2015-02-13 18:53:36 【问题描述】:

例如我有下表:

index,A,B
0,0,0
1,0,8
2,0,8
3,1,0
4,1,5

A分组后:

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

1:
index,A,B
3,1,5
4,1,3

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

B0 中列中行的最大值:8

所以我想删除索引为0 的行并保留索引为12 的行

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

所以我想删除索引为4 的行并保留索引为3 的行

我曾尝试使用pandas过滤功能,但问题是它一次对组中的所有行进行操作:

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

所以我理想情况下需要一些过滤器,它遍历组中的所有行。

感谢您的帮助!

附:还有没有办法只删除组中的行而不返回DataFrame对象?

【问题讨论】:

最后一点是完全模棱两可的:如果您要删除每个组中的行,但返回数据帧,那么您要返回什么? 您的数据在将整个表与组进行比较时,不匹配。请清除它。 抱歉,写这个问题的时候有点忙。现在数据是正确的。好吧,我的意思是从组中删除行并保持这些组原样 - 我需要应用几个过滤器,每次应用后都需要新的 groupby。 df.querypd.eval 似乎很适合这个用例。有关pd.eval() 系列函数、它们的特性和用例的信息,请访问Dynamic Expression Evaluation in pandas using pd.eval()。 如何将过滤器应用回 groupby 结果。我是否必须将 groupby 结果转换为数据框然后应用过滤器?我想创造一种“拥有”的影响。 dfg=df2[(df2['AcctType']=='E')].groupby('CoaDescription')['TotalExpense'].sum() filter=dfg.apply(lambda g: g >10000) dfg=dfg [过滤器] ax=sns.barplot(y=dfg.index,x=dfg) plt.show() 【参考方案1】:

您只需要在groupby 对象上使用apply。我修改了您的示例数据以使其更加清晰:

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()]))

哪些打印:

         A  B
A index      
1 2      1  6
2 4      2  7

【讨论】:

谢谢,它工作正常。请问一下,apply()具体是做什么的?我对g[g['B'] 有点困惑 @jirinovo groupby.apply(function) 通过该函数运行每个组并连接所有结果。 g[...] 是花哨/布尔索引——这意味着它只返回内部条件为真的行。在这种情况下,条件为g['B'] == g['B'].max(),例如,B 列中的值等于该组中 B 的最大值的所有行。 哇,我不知道布尔索引之类的东西——它真的很酷!谢谢。 谢谢。我个人认为 filter 函数不根据某些标准过滤行是一种误导。感觉就像明显的行为。 @gustafbstrom 好的【参考方案2】:

编辑:我刚刚学会了一种更简洁的方法来使用.transform group by method:

def get_max_rows(df):
    B_maxes = df.groupby('A').B.transform(max)
    return df[df.B == B_maxes] 

B_maxes 是一个系列,其索引与原始 df 相同,包含每个 A 组的 B 的最大值。您可以将许多函数传递给 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

编辑:

这是一个抽象,它允许您使用任何有效的比较运算符和任何有效的 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))

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

get_group_rows(df, 'A', 'B', 'median', '>')

几个例子:

%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

【讨论】:

我不得不减少咖啡的摄入,因为 pandas 的文档让我的血压飙升……请问您是从哪里得知这件事的?另外,请允许我link to the transform() doc page 我喜欢 Pandas,但文档、错误消息和测试仍有不足之处。我不记得我第一次看到transform 在哪里使用,但我很确定它就在这里。我经常通过查看这里的问题和答案来找到解决问题的新方法。如果您使用ipython notebook,您可以使用制表符完成来扫描各种方法,阅读文档字符串(我知道不是很好)并尝试它们(在这种情况下,按对象创建一个组并扫描其方法) @mccc 您需要查看人工编写的文档,而不是自动生成的参考:pandas.pydata.org/pandas-docs/stable/… 如果没有像 max, mean, ... 这样的聚合函数,这也能工作吗?因此,例如,如果我只想返回 'some_column == 1' 的组行? 这真的很棒;知道我们如何应用多个过滤条件吗?【参考方案3】:

这是另一个示例:使用 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

【讨论】:

【参考方案4】:

所有这些答案都很好,但我想要以下:

(DataframeGroupby object) --> filter some rows out --> (DataframeGroupby object)

耸耸肩,这似乎比我想象的更难更有趣。所以这个班轮完成了我想要的,但它可能不是最有效的方式:)

gdf.apply(lambda g: g[g['team'] == 'A']).reset_index(drop=True).groupby(gdf.grouper.names) 

工作代码示例:

import pandas as pd

def print_groups(gdf): 
    for name, g in gdf: 
        print('\n'+name) 
        print(g)

df = pd.DataFrame('name': ['sue', 'jim', 'ted', 'moe'],
                   'team': ['A', 'A', 'B', 'B'], 
                   'fav_food': ['tacos', 'steak', 'tacos', 'steak'])                               

gdf = df.groupby('fav_food')                                                                                                                                           
print_groups(gdf)                                                                                                                                                      

    steak
        name team fav_food
    1  jim    A    steak
    3  moe    B    steak

    tacos
        name team fav_food
    0  sue    A    tacos
    2  ted    B    tacos

fgdf = gdf.apply(lambda g: g[g['team'] == 'A']).reset_index(drop=True).groupby(gdf.grouper.names)                                                                      
print_groups(fgdf)                                                                                                                                                     

    steak
      name team fav_food
    0  jim    A    steak

    tacos
      name team fav_food
    1  sue    A    tacos

【讨论】:

当你用 Python 编写代码时,为什么每个人都讨厌变量的语义名称? g 是什么意思。 fgdf是什么意思? @bibscy g 用于分组(我认为)。通常使用groupeddf 被广泛用作dataframefgdf = final grouped dataframe(我猜)

以上是关于Python pandas - 在 groupby 之后过滤行的主要内容,如果未能解决你的问题,请参考以下文章

python pandas groupby分组后的数据怎么用

python [groupby]示例groupby #pandas #secret

[Python Cookbook] Pandas Groupby

python pandas中的Groupby:快速方式

Python/Pandas - 结合 groupby 平均值和最小值

Python Pandas groupby 应用 lambda 参数