python - GroupBy 两列,第一级有边距

标签 python pandas dataframe group-by pandas-groupby

我将数据帧按两列分组,并按其他列的总和进行聚合。如何获得同一数据框中第一个分组列的总计?

例如我的数据框是:

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 个答案。

最佳答案

您可以巧妙地使用 pd.Categoricalgroupby 输出中为“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

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

关于python - GroupBy 两列,第一级有边距,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53719607/

相关文章:

python - arr.append(curr) 和 arr.append(curr[ :])

python - 用于在 minion 中运行状态的 Salt Python API

python - 对象词在 Django 中自动分配给模型

python - Django 上传 xls 文件

python - 当值以 '_h' 结尾时,将 pandas DataFrame 值替换为 np.nan

r - 将表的命名列表转换为 data.frame

python - Pandas 提取多列

python - 如何读取带有 timedeltas 和 NaN 的 csv?

python - 使用 python/pandas 的字典理解与 str.contains 进行部分字符串匹配

python - 分配给 pandas DataFrame 的 *new* 子集