将行添加到 Pandas groupby 对象中

6
我正在尝试找出将平均值插入到多级索引Pandas数据帧中的最佳方法。
假设我有一个像这样的数据框:
      metric 1     metric 2    
             R   P        R   P
foo a        0   1        2   3
    b        4   5        6   7
bar a        8   9       10  11
    b       12  13       14  15

我想要得到以下结果:
      metric 1     metric 2    
             R   P        R   P
foo a        0   1        2   3
    b        4   5        6   7
  AVG        2   3        4   5
bar a        8   9       10  11
    b       12  13       14  15
  AVG       10  11       12  13

请注意,我知道可以使用df.mean(level=0)将第0级别的组平均值作为单独的数据框获取。但这不是我想要的--我想将组平均值作为行插入回组中。
我能够得到我想要的结果,但我觉得自己做错了/可能有一个一行代码的方法可以在没有昂贵的Python迭代的情况下完成此操作。以下是我的示例代码:
import numpy as np
import pandas as pd

data = np.arange(16).reshape(4,4)
row_index = [("foo", "a"), ("foo", "b"), ("bar", "a"), ("bar", "b")]
col_index = [("metric 1", "R"), ("metric 1", "P"), ("metric 2", "R"),  
    ("metric 2", "P")]
col_multiindex = pd.MultiIndex.from_tuples(col_index)
df = pd.DataFrame(data, index=pd.MultiIndex.from_tuples(row_index),
    columns=col_multiindex)

new_row_index = []
data = []
for name, group in df.groupby(level=0):
    for index_tuple, row in group.iterrows():
        new_row_index.append(index_tuple)
        data.append(row.tolist())
    new_row_index.append((name, "AVG"))
    data.append(group.mean().tolist())

print pd.DataFrame(data, 
    index=pd.MultiIndex.from_tuples(new_row_index), 
    columns=col_multiindex)

这将导致:
        metric 1     metric 2    
               R   P        R   P
bar a          8   9       10  11
    b         12  13       14  15
    AVG       10  11       12  13
foo a          0   1        2   3
    b          4   5        6   7
    AVG        2   3        4   5

这个会将一些组的顺序翻转,但大体上来说是我想要的。

你能展示一下你的代码吗?你尝试过什么? - Bono
使用 groupby 对象的 transform 方法。 - Paul H
@Bono 我已经添加了一个代码示例,展示我目前所做的工作。 @PaulH 我不想“转换”数据,只是计算一些聚合统计信息并插入回数据框中。 - kedz
1个回答

3

在这里需要做的主要事情是将你的手段附加到主数据集上。在执行此操作之前,你需要掌握一项关键技巧,即通过使用reset_index()set_index()来使索引相符,这样在附加之后,它们将更或多或少地排列并准备好根据相同的键进行排序。

In [35]: df2 = df.groupby(level=0).mean()

In [36]: df2['index2'] = 'AVG'

In [37]: df2 = df2.reset_index().set_index(['index','index2']).append(df).sort()

In [38]: df2
Out[38]: 
             metric 1     metric 2    
                    R   P        R   P
index index2                          
bar   AVG          10  11       12  13
      a             8   9       10  11
      b            12  13       14  15
foo   AVG           2   3        4   5
      a             0   1        2   3
      b             4   5        6   7

就行的排序而言,最好的方法可能是将名称设置为使其排序到正确位置(例如A、B、avg)。或者对于少量行,您可以使用高级索引:

In [39]: df2.ix[[4,5,3,1,2,0]]
Out[39]: 
             metric 1     metric 2    
                    R   P        R   P
index index2                          
foo   a             0   1        2   3
      b             4   5        6   7
      AVG           2   3        4   5
bar   a             8   9       10  11
      b            12  13       14  15
      AVG          10  11       12  13

谢谢,这正是我在寻找的! - kedz

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