在 pandas muiltiindex 中添加小计/总计行会生成元组作为索引

Posted

技术标签:

【中文标题】在 pandas muiltiindex 中添加小计/总计行会生成元组作为索引【英文标题】:Adding subtotal / grand total row in pandas muiltiindex produces tuple as an index 【发布时间】:2022-01-19 10:54:54 【问题描述】:

我有一个df

df = pd.DataFrame.from_dict('category': 1050: 'Dining',
  992: 'Dining',
  1054: 'Kitchen',
  1052: 'Kitchen',
  993: 'Living room',
  980: 'Living room',
  996: 'Dining',
  1017: 'Dining',
  1020: 'Bath',
  1001: 'Bath',
 'subcategory': 1050: 'Chairs',
  992: 'Chairs',
  1054: 'Stool',
  1052: 'Mirror',
  993: 'mirror',
  980: 'chair',
  996: 'Chairs',
  1017: 'Chairs',
  1020: 'Table',
  1001: 'Table',
 'discount': 1050: '30-40',
  992: '30-40',
  1054: '30-40',
  1052: '30-40',
  993: '30-40',
  980: '30-40',
  996: '30-40',
  1017: '30-40',
  1020: '30-40',
  1001: '30-40',
 'sales_1': 1050: 9539.86,
  992: 12971.86,
  1054: 6736.53,
  1052: 7163.16,
  993: 8601.16,
  980: 8047.16,
  996: 16322.0,
  1017: 14424.32,
  1020: 6319.58,
  1001: 4551.42,
 'sales_2': 1050: 3226.0,
  992: 11117.0,
  1054: 1613.0,
  1052: 2166.0,
  993: 11117.0,
  980: 3442.0,
  996: 19365.0,
  1017: 3323.0,
  1020: 1411.0,
  1001: 572.0)

我正在尝试在多索引中添加小计。 我可以像这样添加 2 个组:

dd =  df_from_dict.groupby(['category', 'subcategory'])[['sales_1', 'sales_2']].sum()

s = dd.groupby(level=0).sum()
s.index = pd.MultiIndex.from_product([s.index, ['Total']])
dd = dd.append(s).sort_index()
dd.loc['Grand Total', :] = dd.sum().values / 2

dd

但是当我将第三项添加到组时,discount

dd =  df_from_dict.groupby(['category', 'subcategory','discount'])[['sales_1', 'sales_2']].sum()

s = dd.groupby(level=0).sum()
s.index = pd.MultiIndex.from_product([s.index, ['Total']])
dd = dd.append(s).sort_index()
dd.loc['Grand Total', :] = dd.sum().values / 2

dd

突然间我得到tuples 而不是正常的多索引。而不是 3 个索引,我得到 1 作为tuple

而我想要与第一张图片中相同的结构,但具有另一个级别的索引。我尝试在 group by 中使用 level=1 参数,但它总是以单个索引作为元组结束,我不确定我的错误在哪里。

【问题讨论】:

【参考方案1】:

Series 中的问题称为 s 是 2 级 MultiIndex,dd 是 3 级,所以在 append 中创建 tuple

解决方案在MultiIndex.from_product 中设置了 3 个级别MultiIndex,因此与dd 相同的数字级别和解决方案工作正常:

为了避免在DataFrame.sort_index 中对所有其他级别进行排序,请添加sort_remaining=False

dd =  df_from_dict.groupby(['category', 'subcategory','discount'])[['sales_1', 'sales_2']].sum()

s = dd.groupby(level=0).sum()
s.index = pd.MultiIndex.from_product([s.index, ['Total'], ['']])
print (s)

dd = dd.append(s).sort_index(level=0, sort_remaining=False)
dd.loc['Grand Total', :] = dd.sum().values / 2
print (dd)
                                   sales_1  sales_2
category    subcategory discount                   
Bath        Table       30-40     10871.00   1983.0
            Total                 10871.00   1983.0
Dining      Chairs      30-40     53258.04  37031.0
            Total                 53258.04  37031.0
Kitchen     Mirror      30-40      7163.16   2166.0
            Stool       30-40      6736.53   1613.0
            Total                 13899.69   3779.0
Living room chair       30-40      8047.16   3442.0
            mirror      30-40      8601.16  11117.0
            Total                 16648.32  14559.0
Grand Total                       94677.05  57352.0

【讨论】:

谢谢,我明白了。知道为什么在living room 类别中,Total 在我们对索引进行排序时不在最后一个位置吗? @JonasPalačionis - 因为.sort_index() @JonasPalačionis - 为避免它而编辑了答案。

以上是关于在 pandas muiltiindex 中添加小计/总计行会生成元组作为索引的主要内容,如果未能解决你的问题,请参考以下文章

从字典中添加具有映射值的新熊猫列[重复]

pandas小技巧

改进 IPython 小部件中 Pandas DataFrames 的 HTML 样式

Pandas不容错过的Pandas小技巧:万能转格式轻松合并压缩数据,让数据分析更高效

在 pyspark.pandas 中添加/减去日期时间

通过在 pandas 中添加 timedelta 来添加时间列