通过子结果聚合多个类别

2024-09-28 21:09:09 发布

您现在位置:Python中文网/ 问答频道 /正文

这似乎是一个很简单的问题,但我就是找不到任何相关信息。
我有数据帧:

df = pd.DataFrame({'x':[1,3,1,3,1,5,1,5],
                   'cat1':['A','A','B','B','A','A','B','B'],
                  'cat2':['A','A','A','A','B','B','B','B']})

    cat1 cat2 x
0   A    A    1
1   A    A    3
2   B    A    1
3   B    A    3
4   A    B    1
5   A    B    5
6   B    B    1
7   B    B    5

其中cat1和cat2是一些类别,我希望使用一些聚合函数(sum、加权平均或定义的东西)在它们上面聚合x。显而易见的解决办法,比如

res = df.groupby(['cat1','cat2']).sum()

结果

           x
cat1 cat2   
A    A     4
     B     6
B    A     4
     B     6

但我想要的是:

    cat1    cat2    x
0   A       A       4
1   A       B       6
2   A       Any     10
3   B       A       4
4   B       B       6
5   B       Any     10
6   Any     A       8
7   Any     B       12
8   Any     Any     20

一种方法是这样:

res2 = df.groupby(['cat1','cat2']).sum().reset_index()
res1a = df.groupby(['cat1']).sum().reset_index()
res1b = df.groupby(['cat2']).sum().reset_index()
res1a['cat2'] = 'any'
res1b['cat1'] = 'any'
res = res1a.append(res1b).append(res2).set_index(['cat1','cat2'])

但由于我的实际任务涉及大约10个类别,因此为不同的类别子集创建单独的groupby并将其全部附加在一起并不方便。我希望有更好的办法


Tags: dfindexanyres类别resetsumgroupby
1条回答
网友
1楼 · 发布于 2024-09-28 21:09:09

可以使用^{}进行重塑,使用sum添加新列和新行Any,最后一次重塑^{}

#add `['x']` for Series output
res = df.groupby(['cat1','cat2'])['x'].sum()
print (res)
cat1  cat2
A     A       4
      B       6
B     A       4
      B       6
Name: x, dtype: int64

a = res.unstack()
a['Any'] = a.sum(axis=1)
a.loc['Any'] = a.sum()
print (a)
cat2  A   B  Any
cat1            
A     4   6   10
B     4   6   10
Any   8  12   20

df1 = a.stack()
print (df1)
cat1  cat2
A     A        4
      B        6
      Any     10
B     A        4
      B        6
      Any     10
Any   A        8
      B       12
      Any     20
dtype: int64

编辑:

res2 = df.groupby(['cat1','cat2']).sum()
res1a = df.groupby(['cat1']).sum()
res1b = df.groupby(['cat2']).sum()
res1a = res1a.set_index(pd.Series(['any'] * len(res1a), name='cat2'), append=True)
res1b=res1b.set_index(pd.Series(['any'] * len(res1b), name='cat1'), append=True).swaplevel()
res1ab=pd.DataFrame(res1a.sum().values, 
                   index=pd.MultiIndex.from_arrays([['any'],['any']]),
                   columns=['x'])

res2 = pd.concat([res2, res1a, res1b, res1ab])
print (res2)
            x
cat1 cat2    
A    A      4
     B      6
B    A      4
     B      6
A    any   10
B    any   10
any  A      8
     B     12
     any   20

相关问题 更多 >