Python GroupBy两列,第一级留有边距
我将一个数据帧按2列分组,并按其他列的总和进行聚合。如何通过同一数据帧中的第一个分组列获得总计 例如,我的数据框是:Python GroupBy两列,第一级留有边距,python,pandas,dataframe,group-by,pandas-groupby,Python,Pandas,Dataframe,Group By,Pandas Groupby,我将一个数据帧按2列分组,并按其他列的总和进行聚合。如何通过同一数据帧中的第一个分组列获得总计 例如,我的数据框是: np.random.seed(0) df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'], 'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
np.random.seed(0)
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
'C' : np.random.randn(8),
'D' : np.random.randn(8)})
结果:
grouped = df.groupby(by=['A', 'B']).sum()
是:
我想要得到什么:
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
如何做到这一点
更新:我发现了一个类似的问题,该问题还有两个答案。您可以使用
pd.category
在groupby
输出中为“total”创建占位符。这将使计算和将总数分配回结果变得容易
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
如果需要根据不同的指标进行聚合:
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
另一种选择是
pivot\u table
,它使保证金生成更容易(尽管不提供次级保证金):
你的问题解决了吗?将来,为了再现性,请在生成随机值之前添加一个随机种子。@IMCoins-否。它添加了一列我需要一个新的多重索引。@coldspeed-你说得对,但这只是一个例子。嗨,coldspeed,我认为这是一个很好的答案,解决了OP的问题。我只是想知道:有没有更简单的方法来获得小计(各种形式的)。得出这个答案需要相当多的经验,而这个问题本身对于分析师和记者来说是非常常见的。它很好,适用于一个聚合数据,但不适用于两个或更多(如我所需)它适用于:df.groupby(by=['a','B']).agg('count'),但不适用于:df.groupby(by=['a','B']).agg(['count','sum'])而且它对df.groupby(by=['A','B']).agg(['count'])也不起作用(因为括号??)@sandervandendoord大多数时候,用户对页边距的要求很容易通过交叉表和透视表等功能得到满足(请参见编辑)。groupby的小计很少被要求,至少从我在这里的经历来看是这样。非常感谢@coldspeed@coldspeed“基于不同指标的聚合”部分是我需要的,但它有一个问题。“groupby”,idx未排序时的排序级别为0。因此,当您重新索引时,您将取消对结果的排序,但“v.groupby(level=0).sum().values”将对结果进行排序。在结果中,您将“total bar”和“total foo”相加,反之亦然。因此,您需要将最后一行更改为“v.groupby(level=0,sort=False).sum()”,或者更好的方法是对idx进行排序(不确定如何排序),它可能适用于2级索引,但不确定是否适用于3级或更高级别(我只有2级,所以它很好,我仍然需要检查)
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
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