【问题标题】:How do I Pandas group-by to get sum?我如何熊猫分组获得总和?
【发布时间】:2017-02-16 19:00:36
【问题描述】:

我正在使用这个数据框:

Fruit   Date      Name  Number
Apples  10/6/2016 Bob    7
Apples  10/6/2016 Bob    8
Apples  10/6/2016 Mike   9
Apples  10/7/2016 Steve 10
Apples  10/7/2016 Bob    1
Oranges 10/7/2016 Bob    2
Oranges 10/6/2016 Tom   15
Oranges 10/6/2016 Mike  57
Oranges 10/6/2016 Bob   65
Oranges 10/7/2016 Tony   1
Grapes  10/7/2016 Bob    1
Grapes  10/7/2016 Tom   87
Grapes  10/7/2016 Bob   22
Grapes  10/7/2016 Bob   12
Grapes  10/7/2016 Tony  15

我想将其按Name 和水果进行汇总,得到每个Name 的Fruit 总数。例如:

Bob,Apples,16

我尝试按Name 和Fruit 进行分组,但我如何获得Fruit 的总数?

【问题讨论】:

标签: python pandas dataframe group-by aggregate


【解决方案1】:

使用GroupBy.sum:

df.groupby(['Fruit','Name']).sum()

Out[31]: 
               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Grapes  Bob        35
        Tom        87
        Tony       15
Oranges Bob        67
        Mike       57
        Tom        15
        Tony        1

【讨论】:

  • pandas 怎么知道我想对名为Number 的列求和?
  • @Kingname 如果去掉 NAME 和 FRUIT,它是最后一列。如果你在左边添加 2 列,它会将两列相加
  • 如何指定对哪一列求和?
  • @tgdn df.groupby(['Name', 'Fruit'])['Number'].sum()
  • @StevenG 对于为总结特定列而提供的答案,输出以 Pandas 系列而不是 Dataframe 的形式出现。根据 Jakub Kukul 的评论(在下面的答案中),我们可以在“数字”周围使用双方括号来获取数据框。
【解决方案2】:

其他两个答案都完成了您想要的。

您可以使用pivot 功能将数据排列在一个漂亮的表格中

df.groupby(['Fruit','Name'],as_index = False).sum().pivot('Fruit','Name').fillna(0)



Name    Bob     Mike    Steve   Tom    Tony
Fruit                   
Apples  16.0    9.0     10.0    0.0     0.0
Grapes  35.0    0.0     0.0     87.0    15.0
Oranges 67.0    57.0    0.0     15.0    1.0

【讨论】:

    【解决方案3】:

    你也可以使用agg函数,

    df.groupby(['Name', 'Fruit'])['Number'].agg('sum')
    

    【讨论】:

    • 这与接受的答案不同,因为它返回 Series 而另一个返回 GroupBy 对象。
    • @GaurangTandon 获取DataFrame 对象(如在接受的答案中),在'Number' 周围使用双方括号,即:df.groupby(['Name', 'Fruit'])[['Number']].agg('sum')
    • 非常有助于清理编码错误的查询报告。
    【解决方案4】:
    df.groupby(['Fruit','Name'])['Number'].sum()
    

    您可以选择不同的列来对数字求和。

    【讨论】:

      【解决方案5】:

      如果要保留原始列 Fruit 和 Name,请使用 reset_index()。否则Fruit 和Name 将成为索引的一部分。

      df.groupby(['Fruit','Name'])['Number'].sum().reset_index()
      
      Fruit   Name       Number
      Apples  Bob        16
      Apples  Mike        9
      Apples  Steve      10
      Grapes  Bob        35
      Grapes  Tom        87
      Grapes  Tony       15
      Oranges Bob        67
      Oranges Mike       57
      Oranges Tom        15
      Oranges Tony        1
      

      如其他答案所示:

      df.groupby(['Fruit','Name'])['Number'].sum()
      
                     Number
      Fruit   Name         
      Apples  Bob        16
              Mike        9
              Steve      10
      Grapes  Bob        35
              Tom        87
              Tony       15
      Oranges Bob        67
              Mike       57
              Tom        15
              Tony        1
      

      【讨论】:

        【解决方案6】:

        您可以将groupby 列设置为index,然后使用sum 和level

        df.set_index(['Fruit','Name']).sum(level=[0,1])
        Out[175]: 
                       Number
        Fruit   Name         
        Apples  Bob        16
                Mike        9
                Steve      10
        Oranges Bob        67
                Tom        15
                Mike       57
                Tony        1
        Grapes  Bob        35
                Tom        87
                Tony       15
        

        【讨论】:

          【解决方案7】:

          .agg() 函数的变体;提供以下功能:(1) 持久化类型 DataFrame,(2) 应用平均值、计数、总和等,以及 (3) 在多列上启用 groupby,同时保持易读性。

          df.groupby(['att1', 'att2']).agg({'att1': "count", 'att3': "sum",'att4': 'mean'})
          

          使用你的价值观...

          df.groupby(['Name', 'Fruit']).agg({'Number': "sum"})
          

          【讨论】:

            【解决方案8】:

            您也可以在 group by 之后在 Number 列上使用 transform()。此操作将使用函数sum 计算一组中的总数,结果是与原始数据帧具有相同索引的系列。

            df['Number'] = df.groupby(['Fruit', 'Name'])['Number'].transform('sum')
            df = df.drop_duplicates(subset=['Fruit', 'Name']).drop('Date', 1)
            

            然后,您可以删除列Fruit 和Name 上的重复行。此外,您可以通过指定轴1 来删除列Date(0 用于行,1 用于列)。

            # print(df)
            
                  Fruit   Name  Number
            0    Apples    Bob      16
            2    Apples   Mike       9
            3    Apples  Steve      10
            5   Oranges    Bob      67
            6   Oranges    Tom      15
            7   Oranges   Mike      57
            9   Oranges   Tony       1
            10   Grapes    Bob      35
            11   Grapes    Tom      87
            14   Grapes   Tony      15
            
            # You could achieve the same result with functions discussed by others: 
            # print(df.groupby(['Fruit', 'Name'], as_index=False)['Number'].sum())
            # print(df.groupby(['Fruit', 'Name'], as_index=False)['Number'].agg('sum'))
            

            有一个官方教程Group by: split-apply-combine谈论分组后你可以做什么。

            【讨论】:

            • 这正是我想要的!我迷失了如何将sum 值从groupby()[].sum() 添加到“唯一”数据框!谢谢!
            【解决方案9】:

            你可以使用 dfsql
            对于您的问题,它看起来像:

            df.sql('SELECT fruit, sum(number) GROUP BY fruit')
            

            https://github.com/mindsdb/dfsql

            这是一篇关于它的文章:

            https://medium.com/riselab/why-every-data-scientist-using-pandas-needs-modin-bringing-sql-to-dataframes-3b216b29a7c0

            【讨论】:

              猜你喜欢
              相关资源
              最近更新 更多