Вы можете стать умнее с pd.Categorical
, чтобы создать заполнитель для "total" в выводе groupby
.Это облегчит вычисление и присвоит итоговое значение результату.
df.B = pd.Categorical(
df.B, categories=np.append(df.B.unique(), 'total'))
v = df.groupby(by=['A', 'B']).sum()
v.loc(axis=0)[pd.IndexSlice[:,'total']] = v.groupby(level=0).sum().values
print(v)
C D
A B
bar one 0.400157 0.410599
two -0.977278 0.121675
three 2.240893 1.454274
total 1.663773 1.986547
foo one 2.714141 0.340644
two 2.846296 0.905081
three -0.151357 0.333674
total 5.409080 1.579400
Если вам нужно агрегировать по разным показателям:
df.B = pd.Categorical(
df.B, categories=np.append(df.B.unique(), 'total'))
idx = pd.MultiIndex.from_product([df.A.unique(), df.B.cat.categories])
v = df.groupby(by=['A', 'B']).agg(['sum', 'count']).reindex(idx)
v.loc(axis=0)[pd.IndexSlice[:,'total']] = v.groupby(level=0, sort=False).sum().values
print(v)
C D
sum count sum count
foo one 2.714141 2.0 0.340644 2.0
two 2.846296 2.0 0.905081 2.0
three -0.151357 1.0 0.333674 1.0
total 5.409080 5.0 1.579400 5.0
bar one 0.400157 1.0 0.410599 1.0
two -0.977278 1.0 0.121675 1.0
three 2.240893 1.0 1.454274 1.0
total 1.663773 3.0 1.986547 3.0
Другой альтернативой является pivot_table
, которая упрощает генерацию маржи (хотя и не обеспечивает маржу подуровня):
df.pivot_table(index=['A', 'B'],
values=['C', 'D'],
aggfunc=['sum', 'count'],
margins=True)
sum count
C D C D
A B
bar one 0.400157 0.410599 1.0 1.0
two -0.977278 0.121675 1.0 1.0
three 2.240893 1.454274 1.0 1.0
foo one 2.714141 0.340644 2.0 2.0
two 2.846296 0.905081 2.0 2.0
three -0.151357 0.333674 1.0 1.0
All 7.072852 3.565947 8.0 8.0