【问题标题】:GroupBy two columns with margins for first levelGroupBy 两列,第一级有边距
【发布时间】:2019-05-12 04:13:24
【问题描述】:

我将数据框按 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
    three  2.240893  1.454274
    two   -0.977278  0.121675
foo one    2.714141  0.340644
    three -0.151357  0.333674
    two    2.846296  0.905081

我会得到什么:

                  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

怎么做?

更新:我在Pandas groupby and sum total of group 发现了一个类似的问题,这个问题还有 2 个答案。

【问题讨论】:

  • this 能解决你的问题吗?
  • 以后为了重现性,请在生成随机值之前添加一个随机种子。
  • @IMCoins - 没有。它添加了一个列,我需要一个新的 multyIndex。
  • @coldspeed - 你说得对,但这只是一个例子。

标签: python pandas dataframe group-by pandas-groupby


【解决方案1】:

您可以巧妙地使用pd.Categorical 在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

【讨论】:

  • 嗨,coldspeed,我认为这是一个很好的答案,可以解决 OP 的问题。我只是想知道:是否有更简单的方法来获取小计(所有形式)。想出这个答案需要相当多的熊猫经验,而这个问题本身对于分析师和记者来说是一个很常见的问题。
  • 这很好,适用于一个聚合数据,但不适用于两个或更多(如我需要)它适用于:df.groupby(by=['A', 'B']).agg ('count') 但不适用于: df.groupby(by=['A', 'B']).agg(['count','sum']) 并且它不适用于 df.groupby(by= ['A', 'B']).agg(['count']) 也是(因为括号??)
  • @SandervandenOord 大多数时候,crosstab 和 pivot_table 等功能可以轻松满足用户对边距的要求(参见编辑)。至少从我在这里看到的情况来看,很少需要 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级所以会很好,我还需要检查它)
猜你喜欢
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 2016-01-21
相关资源
最近更新 更多