【问题标题】:How to select rows from Pandas dataframe after using groupby?使用 groupby 后如何从 Pandas 数据框中选择行?
【发布时间】:2018-02-06 04:56:20
【问题描述】:

从下面的数据框中,如何在不借助复制/粘贴或中间数据结构的情况下获得拥有两只以上宠物的所有者列表?

df = pd.DataFrame([['Jack', 'fuzzy',12], ['Jack', 'furry',13], ['Joe', 'scratchy',3], ['Jack', 'chirpy',40], ['Jeff', 'slithery',9], ['Jack', 'swimmy',1], ['Joe', 'feathery',14], ['Joe', 'oinky',11], ['Jack', 'stampy',1]],
                  columns=['Owner', 'Pet', 'Age'])
print(df)


  Owner       Pet  Age
0  Jack     fuzzy   12
1  Jack     furry   13
2   Joe  scratchy    3
3  Jack    chirpy   40
4  Jeff  slithery    9
5  Jack    swimmy    1
6   Joe  feathery   14
7   Joe     oinky   11
8  Jack    stampy    1

得到一个符合条件的布尔序列很容易:

df.groupby('Owner').count()['Pet']>2

Owner
Jack     True
Jeff    False
Joe      True
Name: Pet, dtype: bool

实际上提取匹配项(JackJoe)可以通过复制粘贴 groupby 语句来完成:

df.groupby('Owner').count()['Pet'][df.groupby('Owner').count()['Pet']>2] 

Owner
Jack    5
Joe     3
Name: Pet, dtype: int64

但如果条件语句很长,这会很痛苦,因为每次更改都需要重复。到目前为止发现的唯一另一种方法是将系列放回数据框并使用query(),但这感觉不太可能:

pd.DataFrame(df.groupby('Owner').count()['Pet']).query('Pet > 2')

       Pet
Owner     
Jack     5
Joe      3

还有比这些更好的方法吗?

【问题讨论】:

  • 避免在 cmets 中回答问题。
  • 您的意思是复制您不想只是将结果分配给变量并对其进行处理?
  • @MedAli 通过复制/粘贴我的意思是这个字符串:df.groupby('Owner').count()['Pet']
  • 感觉你是在夸大问题。您可以分配给另一个变量并对其进行处理df1= df.groupby('Owner').count()['Pet']

标签: python-3.x pandas dataframe series pandas-groupby


【解决方案1】:

您可以使用带有过滤功能的.loc 索引器。

>>> df.groupby('Owner').Pet.count().loc[lambda p: p > 2]
Owner
Jack    5
Joe     3
Name: Pet, dtype: int64

或者,您可以使用compress 方法。

>>> df.groupby('Owner').Pet.count().compress(lambda p: p > 2)
Owner
Jack    5
Joe     3
Name: Pet, dtype: int64

【讨论】:

    【解决方案2】:

    选项 1
    使用pd.factorizenp.bincount

    f, u = pd.factorize(df.Owner.values)
    b = np.bincount(f)
    m = b > 2
    u[m]
    
    array(['Jack', 'Joe'], dtype=object)
    

    或者制作一个系列

    pd.Series(b[m], u[m])
    
    Jack    5
    Joe     3
    dtype: int64
    

    选项 2
    使用相同的groupby 两次

    2.1
    时髦的lambda

    (lambda p: p[p > 2])(df.groupby('Owner').Pet.count())
    
    Owner
    Jack    5
    Joe     3
    Name: Pet, dtype: int64
    

    2.2
    pipe
    我宁愿使用@Mitch 的答案而不是这个答案。

    df.groupby('Owner').Pet.count().pipe(lambda p: p[p > 2])
    
    Owner
    Jack    5
    Joe     3
    Name: Pet, dtype: int64
    

    时间
    下面的代码

    # Multiples of minimum runtime: Smaller is better.
    #
           pir1      pir2      pir3      mch1      mch2
    10      1.0  2.984347  2.907198  2.422435  2.736712
    30      1.0  3.396997  3.464083  3.023355  3.353150
    100     1.0  3.646931  3.053890  2.586377  2.859365
    300     1.0  4.541890  4.037132  3.054388  3.323939
    1000    1.0  2.529670  2.438109  2.214494  2.415056
    3000    1.0  3.212312  3.739621  3.062538  2.969489
    10000   1.0  2.923211  2.807983  2.970712  2.637492
    30000   1.0  2.790350  2.830328  2.978083  2.719900
    

    def pir1(d, c):
        f, u = pd.factorize(d.Owner.values)
        b = np.bincount(f)
        m = b > c
        return pd.Series(b[m], u[m])
    
    pir2 = lambda d, c: (lambda p: p[p > c])(d.groupby('Owner').Pet.count())
    pir3 = lambda d, c: d.groupby('Owner').Pet.count().pipe(lambda p: p[p > c])
    mch1 = lambda d, c: d.groupby('Owner').Pet.count().loc[lambda p: p > c]
    mch2 = lambda d, c: d.groupby('Owner').Pet.count().compress(lambda p: p > c)
    
    res = pd.DataFrame(
        index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
        columns='pir1 pir2 pir3 mch1 mch2'.split(),
        dtype=float
    )
    
    for i in res.index:
        d = pd.concat([df] * i, ignore_index=True)
        c = 2 * i
        for j in res.columns:
            stmt = '{}(d, c)'.format(j)
            setp = 'from __main__ import d, c, {}'.format(j)
            res.at[i, j] = timeit(stmt, setp, number=10)
    
    res.div(res.min(1), 0)
    
    res.plot(loglog=True)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-10
      • 1970-01-01
      相关资源
      最近更新 更多