【问题标题】:Pandas: Selecting rows for which groupby.sum() satisfies conditionPandas:选择 groupby.sum() 满足条件的行
【发布时间】:2017-11-15 20:00:57
【问题描述】:

在熊猫中,我有一个如下形式的数据框:

>>> import pandas as pd  
>>> df = pd.DataFrame({'ID':[51,51,51,24,24,24,31], 'x':[0,1,0,0,1,1,0]})
>>> df

ID   x
51   0
51   1
51   0
24   0
24   1
24   1
31   0

对于每个“ID”,“x”的值被记录多次,它是 0 或 1。我想从 df 中选择那些包含“x”为 1 的“ID”的行至少两次。

对于每个“ID”,我设法计算了“x”为 1 的次数

>>> df.groupby('ID')['x'].sum()

ID
51    1
24    2
31    0

但我不知道如何从这里开始。我想要以下输出:

ID   x
24   0
24   1
24   1

【问题讨论】:

  • 使用 group by 过滤器获取 ID,然后使用结果查询您的主表。我不是 pandas 专家,所以不确定语法。

标签: python pandas pandas-groupby


【解决方案1】:

使用groupbyfilter

df.groupby('ID').filter(lambda s: s.x.sum()>=2)

输出:

   ID  x
3  24  0
4  24  1
5  24  1

【讨论】:

    【解决方案2】:
    df = pd.DataFrame({'ID':[51,51,51,24,24,24,31], 'x':[0,1,0,0,1,1,0]})
    df.loc[df.groupby(['ID'])['x'].transform(func=sum)>=2,:]
    out:
       ID  x
    3  24  0
    4  24  1
    5  24  1
    

    【讨论】:

    • 你不需要第二个索引器并使用'sum'df.loc[df.groupby(['ID'])['x'].transform('sum')>=2]
    • @piRSquared 谢谢~你的回答也让我学到了很多~
    • 我很高兴。希望看到更多你的答案。
    【解决方案3】:

    使用np.bincountpd.factorize
    替代先进技术来获得更好的性能

    f, u = df.ID.factorize()
    df[np.bincount(f, df.x.values)[f] >= 2]
    
       ID  x
    3  24  0
    4  24  1
    5  24  1
    

    以令人讨厌的one-liner 形式

    df[(lambda f, w: np.bincount(f, w)[f] >= 2)(df.ID.factorize()[0], df.x.values)]
    
       ID  x
    3  24  0
    4  24  1
    5  24  1
    

    np.bincountnp.unique
    我可以使用 np.uniquereturn_inverse 参数来完成同样的事情。但是,np.unique 会对数组进行排序,并会改变解的时间复杂度。

    u, f = np.unique(df.ID.values, return_inverse=True)
    df[np.bincount(f, df.x.values)[f] >= 2]
    

    单线

    df[(lambda f, w: np.bincount(f, w)[f] >= 2)(np.unique(df.ID.values, return_inverse=True)[1], df.x.values)]
    

    时机

    %timeit df[(lambda f, w: np.bincount(f, w)[f] >= 2)(df.ID.factorize()[0], df.x.values)]
    %timeit df[(lambda f, w: np.bincount(f, w)[f] >= 2)(np.unique(df.ID.values, return_inverse=True)[1], df.x.values)]
    %timeit df.groupby('ID').filter(lambda s: s.x.sum()>=2)
    %timeit df.loc[df.groupby(['ID'])['x'].transform(func=sum)>=2]
    %timeit df.loc[df.groupby(['ID'])['x'].transform('sum')>=2]
    

    小数据

    1000 loops, best of 3: 302 µs per loop
    1000 loops, best of 3: 241 µs per loop
    1000 loops, best of 3: 1.52 ms per loop
    1000 loops, best of 3: 1.2 ms per loop
    1000 loops, best of 3: 1.21 ms per loop
    

    大数据

    np.random.seed([3,1415])
    df = pd.DataFrame(dict(
            ID=np.random.randint(100, size=10000),
            x=np.random.randint(2, size=10000)
        ))
    
    1000 loops, best of 3: 528 µs per loop
    1000 loops, best of 3: 847 µs per loop
    10 loops, best of 3: 20.9 ms per loop
    1000 loops, best of 3: 1.47 ms per loop
    1000 loops, best of 3: 1.55 ms per loop
    

    更大的数据

    np.random.seed([3,1415])
    df = pd.DataFrame(dict(
            ID=np.random.randint(100, size=100000),
            x=np.random.randint(2, size=100000)
        ))
    
    1000 loops, best of 3: 2.01 ms per loop
    100 loops, best of 3: 6.44 ms per loop
    10 loops, best of 3: 29.4 ms per loop
    100 loops, best of 3: 3.84 ms per loop
    100 loops, best of 3: 3.74 ms per loop
    

    【讨论】:

      猜你喜欢
      • 2015-09-29
      • 1970-01-01
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多