Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python GroupBy两列,第一级留有边距_Python_Pandas_Dataframe_Group By_Pandas Groupby - Fatal编程技术网

Python GroupBy两列,第一级留有边距

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'],

我将一个数据帧按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'],
               '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