【问题标题】:Pandas: Can pandas groupby filter work on original object?熊猫:熊猫 groupby 过滤器可以在原始对象上工作吗?
【发布时间】:2016-10-22 09:10:25
【问题描述】:

从这个问题开始。

Python Pandas: remove entries based on the number of occurrences

data = pandas.DataFrame(
    {'pid' : [1,1,1,2,2,3,3,3],
     'tag' : [23,45,62,24,45,34,25,62],
     })

   #    pid  tag
   # 0    1   23
   # 1    1   45
   # 2    1   62 
   # 3    2   24
   # 4    2   45
   # 5    3   34
   # 6    3   25
   # 7    3   62

   g = data.groupby('tag')
   g.filter(lambda x: len(x) > 1) # filters out lengths > 1. 

  #     pid  tag
  #  1    1   45
  #  2    1   62
  #  4    2   45
  #  7    3   62


 #This would create a new object g: 
 g  =   g.filter(lambda x: len(x) > 1) #where g is now a dataframe. 

我想知道有没有办法通过删除来过滤掉“组” 它们来自原始对象g。而且,它会比从过滤后的 groupby 创建一个新的groupby 对象更快吗?

【问题讨论】:

    标签: python pandas filter group-by


    【解决方案1】:

    几个选项(你的在底部):

    第一个是inplace,我尽可能快地做到了。它比您的解决方案快一点,但不是因为将行放置到位。我可以使用第二个选项获得更好的性能,这不会改变。

    %%timeit
    data = pd.DataFrame(
        {'pid' : [1,1,1,2,2,3,3,3],
         'tag' : [23,45,62,24,45,34,25,62],
         })
    
    mask = ~data.duplicated(subset=['tag'], keep=False)
    data.drop(mask[mask].index, inplace=True)
    data
    
    1000 loops, best of 3: 1.16 ms per loop
    

    %%timeit
    data = pd.DataFrame(
        {'pid' : [1,1,1,2,2,3,3,3],
         'tag' : [23,45,62,24,45,34,25,62],
         })
    
    data = data.loc[data.duplicated(subset=['tag'], keep=False)]
    data
    
    1000 loops, best of 3: 719 µs per loop
    

    %%timeit
    data = pd.DataFrame(
        {'pid' : [1,1,1,2,2,3,3,3],
         'tag' : [23,45,62,24,45,34,25,62],
         })
    g = data.groupby('tag')
    g = g.filter(lambda x: len(x) > 1)
    g
    
    1000 loops, best of 3: 1.55 ms per loop
    

    【讨论】:

    • 它不是重复删除,而是从不需要的分组对象中删除键。需要分组的对象。 groupby 过滤器方法返回一个 DF,我必须从返回的 DF 重新创建 groupby 对象。好像很浪费。
    • 重复的“技巧”是一种识别重复标签的行的厚颜无耻的方式。如果您正在寻找一种有效的方法来删除索引,那是一个不同的问题。我给你拿点东西。
    • 不是索引,而是删除键。我打算用删除键强制执行 for 循环。
    • 不确定我是否理解您对“删除键”和“删除键”之间区别的细微差别。我有另一个想法应该是富有成果的。给我几分钟
    【解决方案2】:

    解决这个问题的方法只有这么多。我的答案包括 4 个解决方案。我敢肯定,还有其他方法。也许其他一些答案会提供更好的方法。

    解决方案 #1:

    data = data.groupby('tag').filter(lambda x: len(x) > 1)
       pid  tag
    1   1   45
    2   1   62
    4   2   45
    7   3   62
    

    解决方案 #2:

    data['count'] = data.groupby(['tag']).transform('count')
    data.loc[data['count'] == 2]
       pid  tag     count
    1   1   45  2
    2   1   62  2
    4   2   45  2
    7   3   62  2
    

    解决方案 #3:

    如果您想删除行,可以使用.index.tolist(),然后使用drop()

    data['count'] = data.groupby(['tag']).transform('count')
    data.drop(data[data['count'] != 2].index.tolist())
       pid  tag     count
    1   1   45  2
    2   1   62  2
    4   2   45  2
    7   3   62  2
    

    解决方案 #4:

    data['count'] = data.groupby(['tag']).transform('count')
    g = data.groupby('count')
    data.loc[g.groups[2],('tag','pid')]
       tag  pid
    1   45  1
    2   62  1
    4   45  2
    7   62  3
    

    【讨论】:

    • 这和上面没有什么不同——返回一个数据框。我需要重新创建 groupby 对象。
    • @Merlin 我添加了另一个解决方案。
    • .@Joe 我正在尝试从 data.groupby('tag') 对象中删除不需要的键。所以,我可以重复使用它。不要创建另一个“g”对象。
    • @Merlin 你可以drop() 不需要的行。请查看我的编辑。
    • .@Joe,因为我有 groupby 对象,它已经扫描了数据帧的行。我认为必须有一种方法来删除键,而不是 delete -drop 行。有意义吗?
    猜你喜欢
    • 2017-05-22
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多