在 Pandas DataFrame groupby 中添加总行

11

我知道这个链接,但我没能解决我的问题。

我有以下代码中的DataFrame:pandas.DataFrame.groupby().sum()

                                                          Value
Level      Company         Item
    1            X            a                             100
                              b                             200
                 Y            a                              35
                              b                             150
                              c                              35
    2            X            a                              48
                              b                             100
                              c                              50
                 Y            a                              80

我希望为每个索引级别添加总行数,以获得以下结果:
                                                          Value
Level      Company         Item
    1            X            a                             100
                              b                             200
                          Total                             300
                 Y            a                              35
                              b                             150
                              c                              35
                          Total                             520
             Total                                          820
    2            X            a                              48
                              b                             100
                              c                              50
             Total                                          198
                 Y            a                              80
                          Total                              80
               Total                                        278
Total                                                      1098

按要求

level = list(map(int, list('111112222')))
company = list('XXYYYXXXY')
item = list('ababcabca')
value = [100,200,35,150,35,48,100,50,80]
col = ['Level', 'Company', 'Item', 'Value']
df = pd.DataFrame([level,company,item,value]).T
df.columns = col
df.groupby(['Level', 'Company', 'Item']).sum()
3个回答

9

您可以使用:

m=df.groupby(['Level','Company','Item'])['Value'].sum().unstack()
m.assign(total=m.sum(1)).stack().to_frame('Value')

                     Value
Level Company Item        
1     X       a      100.0
              b      200.0
              total  300.0
      Y       a       35.0
              b      150.0
              c       35.0
              total  220.0
2     X       a       48.0
              b      100.0
              c       50.0
              total  198.0
      Y       a       80.0
              total   80.0

不错的解决方案,但我无法使其适用于多列求和。该如何解决? - Xavier

2

试一下这个:基本上,它是通过使用两个组的总和创建两个新的数据框,并将三个数据框连接起来。

level = list(map(int, list('111112222')))
company = list('XXYYYXXXY')
item = list('ababcabca')
value = [100,200,35,150,35,48,100,50,80]
col = ['Level', 'Company', 'Item', 'Value']
df = pd.DataFrame([level,company,item,value]).T
df.columns = col

df1 = (df.groupby(['Level', 'Company', 'Item'])['Value'].sum())
df2 = (df1.sum(level=0).to_frame().assign(Company='total').set_index('Company', append=True))
df3 = (df1.groupby(['Level','Company']).sum().to_frame().assign(Item='total').set_index('Item', append=True))

dfx = pd.concat([df1.to_frame().reset_index(),
                 df2.reset_index(),
                 df3.reset_index()],sort=False)
print(dfx)

输出:

   Level Company   Item  Value
0      1       X      a    100
1      1       X      b    200
2      1       Y      a     35
3      1       Y      b    150
4      1       Y      c     35
5      2       X      a     48
6      2       X      b    100
7      2       X      c     50
8      2       Y      a     80
0      1   total    NaN    520
1      2   total    NaN    278
0      1       X  total    300
1      1       Y  total    220
2      2       X  total    198
3      2       Y  total     80

然而,这并不像您预期的那样排序。 如果我将这三个数据框连接起来,而不重置索引,我会得到期望的排序顺序,但是索引是一个多级列。

dfx = pd.concat([df1.to_frame(), df2, df3]).sort_index()

输出

               Value
(1, X, a)        100
(1, X, b)        200
(1, X, total)    300
(1, Y, a)         35
(1, Y, b)        150
(1, Y, c)         35
(1, Y, total)    220
(1, total)       520
(2, X, a)         48
(2, X, b)        100
(2, X, c)         50
(2, X, total)    198
(2, Y, a)         80
(2, Y, total)     80
(2, total)       278

我不确定如何将此转换为与您的数据框中的列相同的格式。


这是你期望的吗? - davidbilla
最后一个数据框出现了KeyError: 'Level'。 - user12392864
我在最初的那个上面做了。错误出现在第四行。df1是一个Series,所以你不能使用groupby,我想这就是问题所在。 - user12392864
使用您的示例,我能够运行此语句 print(df1.groupby(['Level','Company']).sum().to_frame().assign(Company='total').set_index('Company', append=True)),没有任何错误。 - davidbilla
df1.groupby(['Level','Company']).sum().to_frame().assign(Company='total').set_index('Company', append=True) 中的 df1 和下面这行代码中的 df1 是否相同:df1 = (df.groupby(['Level', 'Company', 'Item'])['Value'].sum())?如果是,我们该如何再次对 df1 进行分组操作?在第一行之后,df1 变成了一个 pandas.Series 对象,我们无法再对其进行分组操作。 - user12392864
显示剩余6条评论

2
您可以逐级尝试对其进行堆叠:
m = df.groupby(['Level','Company','Item'])['Value'].sum().unstack(level=['Company','Item'])
m = m.assign(total=m.sum(1))
m = m.stack(level='Company')
m = m.assign(total=m.sum(1))
m = m.stack(level='Item')

输出结果有重复的总数:

Level  Company  Item 
1      X        a        100.0
                b        200.0
                total    300.0
       Y        a         35.0
                b        150.0
                c         35.0
                total    220.0
       total             520.0
                total    520.0
2      X        a         48.0
                b        100.0
                c         50.0
                total    198.0
       Y        a         80.0
                total     80.0
       total             278.0
                total    278.0
dtype: float64

正是我想要的,谢谢!你能帮忙解决一下 https://stackoverflow.com/questions/59364298/adding-total-row-to-a-pandas-dataframe-with-tuples-inside 吗?@Yen - user12392864

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接