【问题标题】:pandas groupby filter, drop some grouppandas groupby 过滤器,删除一些组
【发布时间】:2014-09-05 21:46:21
【问题描述】:

我有 groupby 对象

grouped = df.groupby('name')
for k,group in grouped:    
    print group

有 3 个组 barfoofoobar

  name  time  
2  bar     5  
3  bar     6  


  name  time  
0  foo     5  
1  foo     2  

  name      time  
4  foobar     20  
5  foobar     1  

我需要过滤这些组并删除所有时间不大于 5 的组。 在我的示例中,组 foo 应该被删除。 我正在尝试使用功能 filter()

grouped.filter(lambda x: (x.max()['time']>5))

但 x 显然不仅仅是数据框格式的组。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    通过返回过滤组列表/字典的条件过滤 GroupBy。例如返回长度 >= 5 的组列表/字典。

    返回一个元组列表:

    [(name,gdf) for name,gdf in df.groupby('Declarer') if len(gdf) >= 5]    
    

    返回一个字典:

    {name:gdf for name,gdf in df.groupby('Declarer') if len(gdf) >= 5}
    

    【讨论】:

      【解决方案2】:

      我还不习惯 python、numpy 或 pandas。但是我正在研究类似问题的解决方案,所以让我以这个问题为例报告我的答案。

      import pandas as pd
      
      df = pd.DataFrame()
      df['name'] = ['foo', 'foo', 'bar', 'bar', 'foobar', 'foobar']
      df['time'] = [5, 2, 5, 6, 20, 1]
      
      grouped = df.groupby('name')
      for k, group in grouped:
          print(group)
      

      我的答案1:

      indexes_should_drop = grouped.filter(lambda x: (x['time'].max() <= 5)).index
      result1 = df.drop(index=indexes_should_drop)
      

      我的答案2:

      filter_time_max = grouped['time'].max() > 5
      groups_should_keep = filter_time_max.loc[filter_time_max].index
      result2 = df.loc[df['name'].isin(groups_should_keep)]
      

      我的答案3:

      filter_time_max = grouped['time'].max() <= 5
      groups_should_drop = filter_time_max.loc[filter_time_max].index
      result3 = df.drop(df[df['name'].isin(groups_should_drop)].index)
      

      结果

          name    time
      2   bar     5
      3   bar     6
      4   foobar  20
      5   foobar  1
      

      积分

      My Answer1 不使用组名来删除组。如果您需要组名,您可以通过以下方式获取:df.loc[indexes_should_drop].name.unique()

      grouped['time'].max() &lt;= 5grouped.apply(lambda x: (x['time'].max() &lt;= 5)).index 返回相同的结果。

      filter_time_max 的索引是组名。它不能用作索引或标签以按原样删除。

      name
      foo        True
      bar       False
      foobar    False
      Name: time, dtype: bool
      

      【讨论】:

        【解决方案3】:

        假设你的最后一行代码真的应该有一个&gt;5而不是&gt;20,你会做类似的事情:

        grouped.filter(lambda x: (x.time > 5).any())
        

        正如您正确发现的那样,x 实际上是所有索引的DataFrame,其中name 列与您在for 循环中k 中的键匹配。

        因此,您想根据时间列中是否有任何大于 5 的时间进行过滤,您可以执行上述 (x.time &gt; 5).any() 进行测试。

        【讨论】:

        • 结果是数据框,所以我必须再做一次groupby('name'),对吗? grouped.filter(lambda x: (x.time>5).any()).groupby('name')
        猜你喜欢
        • 1970-01-01
        • 2013-07-10
        • 2013-05-30
        • 2019-02-06
        • 2016-10-01
        • 2017-01-20
        • 2018-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多