如何将层次索引扁平化为列
我有一个数据框,它的列有层级索引(这是通过一个 groupby.agg
操作得到的):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf
sum sum sum sum amax amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
我想把它变得简单一点,像这样(名字不是很重要,我可以重新命名):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf_amax tmpf_amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
我该怎么做呢?(我试了很多方法,但都没成功。)
根据一个建议,这里是字典形式的前几行数据:
{('USAF', ''): {0: '702730',
1: '702730',
2: '702730',
3: '702730',
4: '702730'},
('WBAN', ''): {0: '26451', 1: '26451', 2: '26451', 3: '26451', 4: '26451'},
('day', ''): {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
('month', ''): {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
('s_CD', 'sum'): {0: 12.0, 1: 13.0, 2: 2.0, 3: 12.0, 4: 10.0},
('s_CL', 'sum'): {0: 0.0, 1: 0.0, 2: 10.0, 3: 0.0, 4: 0.0},
('s_CNT', 'sum'): {0: 13.0, 1: 13.0, 2: 13.0, 3: 13.0, 4: 13.0},
('s_PC', 'sum'): {0: 1.0, 1: 0.0, 2: 1.0, 3: 1.0, 4: 3.0},
('tempf', 'amax'): {0: 30.920000000000002,
1: 32.0,
2: 23.0,
3: 10.039999999999999,
4: 19.939999999999998},
('tempf', 'amin'): {0: 24.98,
1: 24.98,
2: 6.9799999999999969,
3: 3.9199999999999982,
4: 10.940000000000001},
('year', ''): {0: 1993, 1: 1993, 2: 1993, 3: 1993, 4: 1993}}
20 个回答
109
pd.DataFrame(df.to_records()) # multiindex become columns and new index is integers only
当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。
226
这个讨论串里的所有回答可能有点过时了。从 pandas
版本 0.24.0 开始,.to_flat_index()
方法可以满足你的需求。
根据 pandas
的官方文档:
MultiIndex.to_flat_index()
将一个多重索引(MultiIndex)转换为包含层级值的元组索引。
文档中的一个简单示例:
import pandas as pd
print(pd.__version__) # '0.23.4'
index = pd.MultiIndex.from_product(
[['foo', 'bar'], ['baz', 'qux']],
names=['a', 'b'])
print(index)
# MultiIndex(levels=[['bar', 'foo'], ['baz', 'qux']],
# codes=[[1, 1, 0, 0], [0, 1, 0, 1]],
# names=['a', 'b'])
使用 to_flat_index()
方法:
index.to_flat_index()
# Index([('foo', 'baz'), ('foo', 'qux'), ('bar', 'baz'), ('bar', 'qux')], dtype='object')
用它替换现有的 pandas
列
这是一个如何在 dat
上使用它的例子,dat
是一个有多重索引列的 DataFrame:
dat = df.loc[:,['name','workshop_period','class_size']].groupby(['name','workshop_period']).describe()
print(dat.columns)
# MultiIndex(levels=[['class_size'], ['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max']],
# codes=[[0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5, 6, 7]])
dat.columns = dat.columns.to_flat_index()
print(dat.columns)
# Index([('class_size', 'count'), ('class_size', 'mean'),
# ('class_size', 'std'), ('class_size', 'min'),
# ('class_size', '25%'), ('class_size', '50%'),
# ('class_size', '75%'), ('class_size', 'max')],
# dtype='object')
就地扁平化和重命名
值得注意的是,你可以将这个方法和简单的列表推导结合使用(感谢 @Skippy 和 @mmann1123),这样可以将元素连接起来,使得最终的列名变成简单的字符串,用下划线等符号分隔:
dat.columns = ["_".join(a) for a in dat.columns.to_flat_index()]
746
我觉得最简单的方法就是把列设置为最顶层:
df.columns = df.columns.get_level_values(0)
注意:如果顶层有名字,你也可以通过这个名字来访问,而不是用0。
.
如果你想把你的多重索引合并成一个索引 (假设你的列里只有字符串内容),你可以这样做:
df.columns = [' '.join(col).strip() for col in df.columns.values]
注意:我们必须 strip
去掉空格,以防没有第二个索引。
In [11]: [' '.join(col).strip() for col in df.columns.values]
Out[11]:
['USAF',
'WBAN',
'day',
'month',
's_CD sum',
's_CL sum',
's_CNT sum',
's_PC sum',
'tempf amax',
'tempf amin',
'year']