【问题标题】:Python - Pandas subtotals on groupbyPython - groupby 上的 Pandas 小计
【发布时间】:2018-05-09 17:38:00
【问题描述】:

这是我使用的数据样本:

SCENARIO    DATE    POD         AREA    IDOC    STATUS  TYPE
AAA   02.06.2015    JKJKJKJKJKK 4210    713375  51         1
AAA   02.06.2015    JWERWERE    4210    713375  51         1
AAA   02.06.2015    JAFDFDFDFD  4210    713375  51         9
BBB   02.06.2015    AAAAAAAA    5400    713504  51        43
CCC   05.06.2015    BBBBBBBBBB  4100    756443  51       187
AAA   05.06.2015    EEEEEEEE    4100    756457  53       228

我在 pandas 中写了以下代码到 groupby:

import pandas as pd
import numpy as np

xl = pd.ExcelFile("MRD.xlsx")
df = xl.parse("Sheet3") 
#print (df.column.values)

# The following gave ValueError: Cannot label index with a null key
# dfi = df.pivot('SCENARIO)

# Here i do not actually need it to count every column, just a specific one
table = df.groupby(["SCENARIO", "STATUS", "TYPE"]).agg(['count'])
writer = pd.ExcelWriter('pandas.out.xlsx', engine='xlsxwriter')
table.to_excel(writer, sheet_name='Sheet1')
writer.save()


table2 = pd.DataFrame(df.groupby(["SCENARIO", "STATUS", "TYPE"])['TYPE'].count())
print (table2)
writer2 = pd.ExcelWriter('pandas2.out.xlsx', engine='xlsxwriter')
table2.to_excel(writer2, sheet_name='Sheet1')
writer2.save()

这会产生一个结果:

SCENARIO  STATUS  TYPE    TYPE
AAA       51      1       2
                  9       1
          53      228     1
BBB       51      43      1
CCC       51      187     1
Name: TYPE, dtype: int64   

如何为每个组添加小计?理想情况下,我希望实现以下目标:

SCENARIO  STATUS  TYPE    TYPE
AAA       51      1       2
                  9       1
          Total           3
          53      228     1
          Total           1
BBB       51      43      1
          Total           1
CCC       51      187     1
          Total           1
Name: TYPE, dtype: int64   

这可能吗?

【问题讨论】:

  • 如果TotalTYPE 级别有问题吗?

标签: python pandas group-by pivot-table


【解决方案1】:

用途:

#if necessary convert TYPE column to string
df['TYPE'] = df['TYPE'].astype(str)
df = df.groupby(["SCENARIO", "STATUS", "TYPE"])['TYPE'].count()

#aggregate sum by first 2 levels
df1 = df.groupby(["SCENARIO", "STATUS"]).sum()
#add 3 level of MultiIndex 
df1.index = [df1.index.get_level_values(0),
            df1.index.get_level_values(1),
            ['Total'] * len(df1)]

#thanks MaxU for improving
#df1 = df1.set_index(np.array(['Total'] * len(df1)), append=True) 

print (df1)
SCENARIO  STATUS       
AAA       51      Total    3
          53      Total    1
BBB       51      Total    1
CCC       51      Total    1
Name: TYPE, dtype: int64

#join together and sorts
df = pd.concat([df, df1]).sort_index(level=[0,1])
print (df)
SCENARIO  STATUS  TYPE 
AAA       51      1        2
                  9        1
                  Total    3
          53      228      1
                  Total    1
BBB       51      43       1
                  Total    1
CCC       51      187      1
                  Total    1
Name: TYPE, dtype: int64

【讨论】:

  • Traceback(最近一次调用最后):文件“C:\Anaconda3\lib\site-packages\pandas\indexes\multi.py”,第 707 行,在 get_value return _index.get_value_at(s, k) 文件“pandas\index.pyx”,第 65 行,在 pandas.index.get_value_at (pandas\index.c:2759) 文件“pandas\src\util.pxd”,第 63 行,在 util.get_value_at (pandas\ index.c:16180) TypeError: 'str' 对象不能被解释为整数
  • 这很有效,遗憾的是,我也想计算 NaN 的数量,不一定在同一个 df 上,也许在一个单独的 df 上。感谢大家的帮助!
  • 是的,这是可能的。喜欢df['TYPE'] = df['TYPE'].fillna(-1).astype(int).astype(str)
  • 非常好的解决方案!与df1.index = [...]相比,我认为df1 = df1.set_index(np.array(['Total'] * len(df1)), append=True) 会更惯用一点
  • @Bowen Liu 当然,它按一级和二级排序索引,想法是在连接后将总计添加到每个级别的末尾。
【解决方案2】:

Chris Moffitt 创建了一个名为sidetable 的库来简化这个过程,它可以与带有访问器的 groupby 对象一起使用,使其非常容易。也就是说,接受的答案和 cmets 是一座金矿,我觉得值得先检查一下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 2023-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    相关资源
    最近更新 更多