Python 如何在多索引数据帧中为每个子索引添加一行?
假设我有以下数据帧:Python 如何在多索引数据帧中为每个子索引添加一行?,python,pandas,Python,Pandas,假设我有以下数据帧: import pandas as pd df = pd.DataFrame( { 'state': ['CA', 'WA', 'CO', 'AZ'] * 3, 'office_id': list(range(1, 7)) * 2, 'sales': [pd.np.random.randint(100000, 999999) for _ in range(12)] } ) 这是: office_id
import pandas as pd
df = pd.DataFrame(
{
'state': ['CA', 'WA', 'CO', 'AZ'] * 3,
'office_id': list(range(1, 7)) * 2,
'sales': [pd.np.random.randint(100000, 999999) for _ in range(12)]
}
)
这是:
office_id sales state
0 1 903325 CA
1 2 364594 WA
2 3 737728 CO
3 4 239378 AZ
4 5 833003 CA
5 6 501536 WA
6 1 920821 CO
7 2 879602 AZ
8 3 661818 CA
9 4 548888 WA
10 5 842459 CO
11 6 906791 AZ
现在,我在office\u id
上执行groupby
操作,并声明
:
df.groupby(["office_id", "state"]).aggregate({"sales": "sum"})
这导致:
sales
office_id state
1 CA 903325
CO 920821
2 AZ 879602
WA 364594
3 CA 661818
CO 737728
4 AZ 239378
WA 548888
5 CA 833003
CO 842459
6 AZ 906791
WA 501536
是否可以为每个办公室id添加一行,并添加一个新索引total
,例如,它是sales列每个状态的总和
我可以通过分组“office\u id”和sum来计算它,但我获得了一个新的数据帧,但我没有成功地将其合并。您可以通过,添加新列总计
,然后通过重新整形,如果需要多索引
使用:
计时:
def jez(df):
df1 = df.groupby(["office_id", "state"])['sales'].sum().unstack()
df1['total'] = df1.sum(axis=1)
df1 = df1.stack().to_frame('sales')
df1.sales = df1.sales
return (df1)
print (jez(df))
In [339]: %timeit (df.pivot_table(index='office_id', columns='state', margins=True, margins_name='total', aggfunc='sum').stack())
100 loops, best of 3: 14.6 ms per loop
In [340]: %timeit (jez(df))
100 loops, best of 3: 2.78 ms per loop
Pandas通过将
边距
参数设置为True
,具有内置的功能,可以通过pivot\u表
完成此操作。它只能正确排序,因为“total”是小写字母,大写字母排在第一位
df.pivot_table(index='office_id', columns='state', margins=True,
margins_name='total', aggfunc='sum').stack()
sales
office_id state
1 CA 415727.0
CO 240142.0
total 655869.0
2 AZ 126350.0
WA 385698.0
total 512048.0
3 CA 387320.0
CO 487075.0
total 874395.0
4 AZ 978018.0
WA 878368.0
total 1856386.0
5 CA 105057.0
CO 852025.0
total 957082.0
6 AZ 130853.0
WA 435940.0
total 566793.0
total AZ 1235221.0
CA 908104.0
CO 1579242.0
WA 1700006.0
total 5422573.0
您还可以使用
concat
附加汇总总数,如下所示
pd.concat([df.groupby(["office_id", "state"]).aggregate({"sales": "sum"}),
df.groupby(["state"]).aggregate({"sales": "sum"})
.set_index([['Total', 'Total', 'Total', 'Total']], append=True).swaplevel(0, 1)])
返回
sales
office_id state
1 CA 914776
CO 902173
2 AZ 605783
WA 865189
3 CA 280203
CO 556867
4 AZ 958747
WA 643333
5 CA 703606
CO 644399
6 AZ 768268
WA 834051
Total AZ 2332798
CA 1898585
CO 2103439
WA 2342573
这里,Data.frame在办公室状态和状态级别进行聚合。它们与.concat
连接在一起。聚合到状态级别的数据帧在合并之前必须提供额外的索引。这是通过set\u index
完成的。此外,索引必须交换以符合office状态级别的数据帧
pd.concat([df.groupby(["office_id", "state"]).aggregate({"sales": "sum"}),
df.groupby(["state"]).aggregate({"sales": "sum"})
.set_index([['Total', 'Total', 'Total', 'Total']], append=True).swaplevel(0, 1)])
sales
office_id state
1 CA 914776
CO 902173
2 AZ 605783
WA 865189
3 CA 280203
CO 556867
4 AZ 958747
WA 643333
5 CA 703606
CO 644399
6 AZ 768268
WA 834051
Total AZ 2332798
CA 1898585
CO 2103439
WA 2342573