【问题标题】:Pandas: how to sum by groupby value熊猫:如何按 groupby 值求和
【发布时间】:2018-10-03 13:34:08
【问题描述】:

使用这个:

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
         'Kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
         'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
         'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

df.groupby(['Team',"Rank"]).sum()

这是返回的。

             Points
Team   Rank        
Devils 2        863
       3        673
Kings  1       1544
       3        741
       4        812
Riders 1        876
       2       2173
Royals 1        804
       4        701

我如何提取等级等于“1”的值(点),即 1544+ 876+ 804。 秩等于 2 和 3 也是如此。

【问题讨论】:

  • 您想要的确切输出是什么?每个等级值一个数据帧,还是每个等级总和以某种方式排序的单个数据帧?
  • df 每个等级的总和以某种方式排序,我想看看,然后对值求和

标签: python pandas dataframe pandas-groupby multi-index


【解决方案1】:

我相信需要DataFrame.xs:

print (df.xs(1, level=1))

        Points
Team          
Kings     1544
Riders     876
Royals     804

print (df.xs(2, level=1))

        Points
Team          
Devils     863
Riders    2173

对于多条件选择,请使用slicers

idx = pd.IndexSlice
print (df.loc[idx[:, [1,2]], :])

             Points
Team   Rank        
Devils 2        863
Kings  1       1544
Riders 1        876
       2       2173
Royals 1        804

print (df.loc[idx['Riders', [1,2]], :])

             Points
Team   Rank        
Riders 1        876
       2       2173

如果想通过Ranks 对所有组求和,请将分组列从['Team',"Rank"] 更改为Rank

s = df.groupby("Rank")['Points'].sum()
print (s)
Rank
1    3224
2    3036
3    1414
4    1513
Name: Points, dtype: int64

如果还需要df1,则使用sum per level=1

df1 = df.groupby(['Team',"Rank"]).sum()
print (df1)
             Points
Team   Rank        
Devils 2        863
       3        673
Kings  1       1544
       3        741
       4        812
Riders 1        876
       2       2173
Royals 1        804
       4        701

s1 = df1.sum(level=1)
print (s1)
      Points
Rank        
2       3036
3       1414
1       3224
4       1513

【讨论】:

  • @Merlin - 是的,像 df1.sum(level='Rank') 一样使用 level='Rank'
【解决方案2】:

也许您可以尝试将groupby 中的列交换为["Rank", "Team"]

grouped = df.groupby(["Rank", "Team"]).sum()
print(grouped)

结果:

             Points
Rank Team          
1    Kings     1544
     Riders     876
     Royals     804
2    Devils     863
     Riders    2173
3    Devils     673
     Kings      741
4    Kings      812
     Royals     701

然后,要获得任何等级的总和,您可以使用loc。例如第一名是:

grouped.loc[1].Points.sum()

结果:

3224

【讨论】:

    【解决方案3】:

    一个选项

    >>> df_group = df.groupby(['Team',"Rank"]).sum().reset_index()
         Team  Rank  Points
    0  Devils     2     863
    1  Devils     3     673
    2   Kings     1    1544
    3   Kings     3     741
    4   Kings     4     812
    5  Riders     1     876
    6  Riders     2    2173
    7  Royals     1     804
    8  Royals     4     701
    

    现在你可以过滤'Rank':

    >>> df_group.loc[df_group['Rank']==1,'Points']
    2    1544
    5     876
    7     804
    

    另一个选项是再次按排名分组,然后聚合为一个列表:

    >>> df.groupby(['Team','Rank']).sum().reset_index().groupby('Rank')['Points'].agg(lambda x: list(x))
    Rank
    1    [1544, 876, 804]
    2         [863, 2173]
    3          [673, 741]
    4          [812, 701]
    

    或者您可能只是想按排名排序,这很难说,因为您没有提供所需的输出:

    >>> df.groupby(['Team','Rank']).sum().reset_index().sort_values('Rank')
         Team  Rank  Points
    2   Kings     1    1544
    5  Riders     1     876
    7  Royals     1     804
    0  Devils     2     863
    6  Riders     2    2173
    1  Devils     3     673
    3   Kings     3     741
    4   Kings     4     812
    8  Royals     4     701
    

    【讨论】:

      【解决方案4】:

      我喜欢使用axis argument in .loc

      df.groupby(['Team',"Rank"]).sum().loc(axis=0)[:,1]
      

      输出:

                   Points
      Team   Rank        
      Kings  1       1544
      Riders 1        876
      Royals 1        804
      

      或者

      df.groupby(['Team',"Rank"]).sum().loc(axis=0)[:,2]
      
                   Points
      Team   Rank        
      Devils 2        863
      Riders 2       2173
      

      或者就像@Jezrael 在没有pd.Slicers 的情况下所做的那样:

      df.groupby(['Team',"Rank"]).sum().loc(axis=0)[:,[1,2]]
      
                   Points
      Team   Rank        
      Devils 2        863
      Kings  1       1544
      Riders 1        876
             2       2173
      Royals 1        804
      

      【讨论】:

        【解决方案5】:

        求和后可以按排名重新排序:

        import pandas as pd
        
        ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
                 'Kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
                 'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
                 'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
        df = pd.DataFrame(ipl_data)
        
        result = df.groupby(['Team', 'Rank']).sum().swaplevel().sort_index()
        # Or just:
        result = df.groupby(['Rank', 'Team']).sum()
        
        print(result)
        

        输出:

        Rank Team
        1    Kings     1544
             Riders     876
             Royals     804
        2    Devils     863
             Riders    2173
        3    Devils     673
             Kings      741
        4    Kings      812
             Royals     701
        

        【讨论】:

          【解决方案6】:
          df[df['Rank'] == 1] # Filter by rank before summing
          

          【讨论】:

            猜你喜欢
            • 2021-06-16
            • 2013-10-24
            • 2013-06-06
            • 2019-01-18
            • 2020-09-08
            • 2016-02-20
            • 2019-02-24
            • 1970-01-01
            • 2018-12-09
            相关资源
            最近更新 更多