4 题: Python Pandas:根据出现次数删除条目

在...创建的问题 Mon, Nov 19, 2012 12:00 AM

我正在尝试从数据框中删除少于100次的条目。 数据框data如下所示:

 
pid   tag
1     23    
1     45
1     62
2     24
2     45
3     34
3     25
3     62

现在我计算这样的标签出现次数:

 
bytag = data.groupby('tag').aggregate(np.count_nonzero)

但后来我无法弄清楚如何删除那些计数不足的条目......

    
21
  1. as @ unutbu建议,请考虑更改接受的答案(过滤方法更简单:))
    2014-02-28 21:30:01Z
  2. 醇>
    4个答案                              4 跨度>                         

    编辑:感谢@WesMcKinney以更直接的方式展示:

     
    data[data.groupby('tag').pid.transform(len) > 1]
    

     
    import pandas
    import numpy as np
    data = pandas.DataFrame(
        {'pid' : [1,1,1,2,2,3,3,3],
         'tag' : [23,45,62,24,45,34,25,62],
         })
    
    bytag = data.groupby('tag').aggregate(np.count_nonzero)
    tags = bytag[bytag.pid >= 2].index
    print(data[data['tag'].isin(tags)])
    

    产量

     
       pid  tag
    1    1   45
    2    1   62
    4    2   45
    7    3   62
    
        
    23
    2012-11-25 12:31:33Z
    1. 一个可爱的单行:data [data.groupby('tag')。pid.transform(len)> 1]
      2012-11-25 05:53:54Z
    2. 我们现在有过滤器方法。
      2013-12-10 02:52:22Z
    3. 醇>

    0.12中的新功能,groupby对象有一个 filter 方法,允许你这样做这些类型的操作:

     
    In [11]: g = data.groupby('tag')
    
    In [12]: g.filter(lambda x: len(x) > 1)  # pandas 0.13.1
    Out[12]:
       pid  tag
    1    1   45
    2    1   62
    4    2   45
    7    3   62
    

    函数(过滤器的第一个参数)应用于每个组(子帧),结果包括属于评估为True的组的原始DataFrame的元素。

    注意:在0.12中的排序与原始DataFrame中的排序不同,这在0.13+中已修复:

     
    In [21]: g.filter(lambda x: len(x) > 1)  # pandas 0.12
    Out[21]: 
       pid  tag
    1    1   45
    4    2   45
    2    1   62
    7    3   62
    
        
    25
    2014-02-28 21:27:20Z
    1. 我想知道结果的顺序是否是有意的...
      2013-08-21 12:52:19Z
    2. 感谢您回到这个问题来传播过滤器的福音。重新排序是我应该包含在文档中的已知问题。如果设置dropna=False,则的订单。如果不是,则可以对组进行洗牌。使用它们会花费时间,所以我把它留给了用户,这是一个值得商榷的选择。
      2013-08-21 13:12:29Z
    3. @ DanAllan此外,如果有重复/无序索引,将它们按顺序放回可能并非易事。啊哈,目前你可以这样做:g.filter(lambda x: len(x) > 1, dropna=False).dropna()保持订单。
      2013-08-21 13:23:50Z
    4. @ DanAllan哦不,你不能......因为重新索引不适用于重复。所以过滤器不起作用。提醒你,也不要改变。
      2013-08-21 13:26:00Z
    5. @ sashkello:请考虑将此作为接受的答案。它更简单,是未来的正确方法。
      2014-02-28 20:57:11Z
    6. 醇>
     
    df = pd.DataFrame([(1, 2), (1, 3), (1, 4), (2, 1),(2,2,)], columns=['col1', 'col2'])
    
    In [36]: df
    Out[36]: 
       col1  col2
    0     1     2
    1     1     3
    2     1     4
    3     2     1
    4     2     2
    
    gp = df.groupby('col1').aggregate(np.count_nonzero)
    
    In [38]: gp
    Out[38]: 
          col2
    col1      
    1        3
    2        2
    

    让我们得到计数> 2

     
    tf = gp[gp.col2 > 2].reset_index()
    df[df.col1 == tf.col1]
    
    Out[41]: 
       col1  col2
    0     1     2
    1     1     3
    2     1     4
    
        
    2
    2012-11-19 02:02:21Z
    1. 出于某种原因,我得到空集......
      2012-11-19 02:18:51Z
    2. 现在我有了主意。另一种方法是加入这些数据框,它将删除不匹配的条目,然后我可以删除计数列。
      2012-11-19 02:22:50Z
    3. jep可以工作2.我通常只使用一个掩码,然后选择我需要的cols
      2012-11-19 02:25:24Z
    4. 醇>

    以下是此处发布的几个解决方案的一些运行时间,以及一个不是(使用value_counts())比其他解决方案快得多的解决方案:

    创建数据:

     
    import pandas as pd
    import numpy as np
    
    # Generate some 'users'
    np.random.seed(42)
    df = pd.DataFrame({'uid': np.random.randint(0, 500, 500)})
    
    # Prove that some entries are 1
    print "{:,} users only occur once in dataset".format(sum(df.uid.value_counts() == 1))
    

    输出:

    171 users only occur once in dataset

    使用一个条目删除用户的几种不同方法。这些是在Jupyter笔记本中的不同单元格中运行的:

     
    %%timeit
    df.groupby(by='uid').filter(lambda x: len(x) > 1)
    
    %%timeit
    df[df.groupby('uid').uid.transform(len) > 1]
    
    %%timeit
    vc = df.uid.value_counts()
    df[df.uid.isin(vc.index[vc.values > 1])].uid.value_counts()
    

    这些产生了以下输出:

     
    10 loops, best of 3: 46.2 ms per loop
    10 loops, best of 3: 30.1 ms per loop
    1000 loops, best of 3: 1.27 ms per loop
    
        
    2
    2017-05-03 01:36:16Z
    1. 这肯定是接受的答案。使用value_counts()的那个比其他两个快,特别是对于具有大量组的数据集
      2018-04-03 20:18:05Z
    2. 醇>
来源放置 这里