使用DataFrame.set_index()创建MultiIndex时0和1被转布尔值的问题
问题
使用DataFrame.set_index()将两列转换为MultiIndex时,原本的整数0和1被转换为布尔值False和True。
初始表格(注意idx2列的值):
| | idx1 | idx2 | val | |---:|:-------|:-------|------:| | 0 | A | | 1 | | 1 | B | False | 2 | | 2 | B | True | 3 | | 3 | C | 0 | 4 | | 4 | C | 1 | 5 | | 5 | C | 2 | 6 | | 6 | C | 3 | 7 |
执行df.set_index(['idx1', 'idx2'])后,第4、5行的整数0、1被转为布尔值:
| | val | |:-------------|------:| | ('A', '') | 1 | | ('B', False) | 2 | | ('B', True) | 3 | | ('C', False) | 4 | <<<< 应为 ('C', 0) | ('C', True) | 5 | <<<< 应为 ('C', 1) | ('C', 2) | 6 | | ('C', 3) | 7 |
问题出现在pandas 1.5.3版本中,求原因及解决办法。
最小可复现示例(MWE):
#!/usr/bin/env python3 import pandas df = pandas.DataFrame({ 'idx1': list('ABBCCCC'), 'idx2': ['', False, True, 0, 1, 2, 3], 'val': range(1, 8) }) print(df.to_markdown()) df = df.set_index(['idx1', 'idx2']) print(df.to_markdown())
原因分析
这是因为idx2列是混合类型(包含字符串、布尔值、整数),pandas创建DataFrame时会将该列推断为object类型,但构建MultiIndex时,会尝试统一索引值的类型。由于Python中bool是int的子类,布尔值False/True和整数0/1等价,pandas会优先将0/1转换为对应的布尔值,以保持索引类型的一致性。
解决办法
有两种可靠方式避免该问题:
方法1:将idx2列统一转换为字符串类型
设置索引前,把idx2的所有值转为字符串,这样0、1会被保留为字符串"0"、"1",不会被转成布尔值:
df['idx2'] = df['idx2'].astype(str) df = df.set_index(['idx1', 'idx2'])
转换后的索引会显示为('C', '0')、('C', '1'),完全保留原始值的字面形式。
方法2:使用Categorical类型固定值的类型
如果需要保留原始值的类型信息,可将idx2转为分类类型,强制pandas不自动转换类型:
df['idx2'] = pandas.Categorical(df['idx2'], categories=df['idx2'].unique()) df = df.set_index(['idx1', 'idx2'])
这种方式会保留每个值的原始类型,索引会正确显示为('C', 0)、('C', 1)。
内容的提问来源于stack exchange,提问作者buhtz
相关产品推荐
相关产品推荐

