Pandas 聚合多列

Pandas aggregating across multiple columns

我有以下数据框

import pandas as pd
import numpy as np
from IPython.display import display

arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
         ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
index = pd.MultiIndex.from_arrays(arrays, names=['first', 'second'])
df = pd.DataFrame({'A': np.arange(8),
                   'B': np.arange(8),
                    'C': np.arange(8)},
                  index=index)
df

我现在想要一个数据框,其内容是 'first' 组下所有元素的总和,即

<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
    border: 1px solid black;
}
</style>
</head>
<body>

<table style="width:100%">
  <tr>
    <th>first</th>
    <th>sum</th>     
  </tr>
  <tr>
    <td>bar</td>
    <td>3</td>    
  </tr>
  <tr>
    <td>baz</td>
    <td>15</td>    
  </tr>
  <tr>
    <td>foo</td>
    <td>27</td>    
  </tr>
  <tr>
    <td>qux</td>
    <td>39</td>    
  </tr>
</table>
</body>
</html>

我试过下面的代码

grouped = df.groupby([pd.Grouper(level='first')])
grouped.sum(axis='columns')

但这抱怨 "f() got an unexpected keyword argument 'axis'"。有没有办法通过抑制其中一个索引来 运行 多索引数据帧上的聚合函数?

方式一

这个代码

grouped = df.reset_index().groupby('first').sum()
sum_by_columns = grouped.sum(axis=1).to_frame()
sum_by_columns.columns = ['sum']
print(sum_by_columns)

将提供您想要的输出

       sum
first     
bar      3
baz     15
foo     27
qux     39

这里的士气是 grouped.sum() 分别应用于每一列。

方式二

不过您可以使用自己的聚合函数:

sum_by_columns = df.groupby([pd.Grouper(level='first')]).apply(lambda x: x.sum().sum())
sum_by_columns.columns = ['sum']
print(sum_by_columns)

它会导致您得到相同的结果。在这里,lambda 不是应用于每一列,而是应用于每个部分数据帧。

方式三

如果需要跨列聚合,可以先用df.stack()方法转成行:

sum_by_columns = df.stack().groupby(pd.Grouper(level='first')).sum().to_frame()
sum_by_columns.columns = ['sum']
print(sum_by_columns)
 df.groupby(by="first").sum() will give you, (by="w/e you want them to be group by")
            A   B   C
    first            
    bar     1   1   1
    baz     5   5   5
    foo     9   9   9
    qux    13  13  13

 df.groupby(by="first").sum().sum(axis=1) will give you 
first
bar     3
baz    15
foo    27
qux    39