重新索引缺少类别的多级索引

Posted

技术标签:

【中文标题】重新索引缺少类别的多级索引【英文标题】:reindex multi level index with missing categories 【发布时间】:2021-12-03 15:17:09 【问题描述】:

我有一个带有两个索引的数据框,groupclass。我有一本字典,其中包含需要添加到这两个索引中的其他级别。具体来说,我想将 E 添加到 group 索引中。而且我想确保每个 group 中的所有 g1、g2 和 g3 都存在于 class 索引中(因此将 g3 添加到组 A,将 g1 添加到组 B,g2 和g3 到 C 组,g1 和 g3 到 D 组和 g1、g2 和 g3 到 E 组。我想在适当的地方用零填充总列

原始数据框在这里

df = pd.DataFrame(data='group' : ['A','A','B','B','C','D'],
                        'class': ['g1','g2','g2','g3','g1','g2'],
                        'total' : [3,14,12,11,21,9])

包含所有必需类别的字典(和映射的 df)在这里

dic = 'group':['A','B','C','D','E'],
       'class' : ['g1','g2','g3']

预期的输出就在这里

expectedOutput = pd.DataFrame(data='group' : ['A','A','A','B','B','B','C','C','C','D','D','D','E','E','E'],
                        'class': ['g1','g2', 'g3','g1','g2', 'g3','g1','g2', 'g3','g1','g2', 'g3','g1','g2', 'g3'],
                        'total' : [3,14,0, 0,12,11,21,0,0,0,9,0, 0,0,0])

我在重新编制索引时无法维护重复的值,但我需要将它们全部保留。欢迎大家多多指教,万分感谢

【问题讨论】:

【参考方案1】:

您可以使用漂亮的pyjanitor 模块及其complete 方法:

# pip install pyjanitor
import janitor as jn 
(df.complete('group': list(df['group'].unique())+['D', 'E'], 'class')
   .fillna(0, downcast='infer')
)

输出:

   group class  total
0      A    g1      3
1      A    g2     14
2      A    g3      0
3      B    g1      0
4      B    g2     12
5      B    g3     11
6      C    g1     21
7      C    g2      0
8      C    g3      0
9      D    g1      0
10     D    g2      9
11     D    g3      0
12     E    g1      0
13     E    g2      0
14     E    g3      0

【讨论】:

我认为如果您按原样使用dic,您仍然会得到相同的结果:df.complete(dic).fillna(0, downcast='infer') @sammywemmy 有一个额外的值要添加 (E)。顺便说一句,看,现在我开始使用 pyjanitor ;)【参考方案2】:

使用MultiIndex 的解决方案 - 由MultiIndex.from_product 使用DataFrame.reindexdict 创建:

dic = 'group':['A','B','C','D','E'],
       'class' : ['g1','g2','g3']

mux = pd.MultiIndex.from_product(dic.values(), names=dic)

df = df.set_index(list(dic)).reindex(mux, fill_value=0).reset_index()
print (df)
   group class  total
0      A    g1      3
1      A    g2     14
2      A    g3      0
3      B    g1      0
4      B    g2     12
5      B    g3     11
6      C    g1     21
7      C    g2      0
8      C    g3      0
9      D    g1      0
10     D    g2      9
11     D    g3      0
12     E    g1      0
13     E    g2      0
14     E    g3      0

或者由DataFrame创建的itertools.product左连接:

from  itertools import product

dicDf = pd.DataFrame(product(*dic.values()), columns=dic)

df = dicDf.merge(df, how='left').fillna('total':0)
print (df)
   group class  total
0      A    g1    3.0
1      A    g2   14.0
2      A    g3    0.0
3      B    g1    0.0
4      B    g2   12.0
5      B    g3   11.0
6      C    g1   21.0
7      C    g2    0.0
8      C    g3    0.0
9      D    g1    0.0
10     D    g2    9.0
11     D    g3    0.0
12     E    g1    0.0
13     E    g2    0.0
14     E    g3    0.0

【讨论】:

@ScottBoston - 谢谢,解压再打包,太复杂了。 哦,哇,答案很快,谢谢!我也可以看到我的 dicDf 实际上并没有工作,因为它在“组”中删除项目,其中“类”中没有项目与行级别匹配 *我将更新它

以上是关于重新索引缺少类别的多级索引的主要内容,如果未能解决你的问题,请参考以下文章

数据分析索引总结(中)Pandas多级索引

Pandas系列(十八)- 多重索引

将多级索引的第一级旋转为多级列的第一级

PHP重新索引数组? [复制]

如何在 pyomo 中使用集合和范围集的多级索引?

Pandas extractall() - 返回列表,而不是多级索引?