Python Pandas - 如何在列中展平分层索引
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14507794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pandas - How to flatten a hierarchical index in columns
提问by Ross R
I have a data frame with a hierarchical index in axis 1 (columns) (from a groupby.aggoperation):
我在轴 1(列)中有一个带有分层索引的数据框(来自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
I want to flatten it, so that it looks like this (names aren't critical - I could rename):
我想将它压平,使其看起来像这样(名称并不重要 - 我可以重命名):
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
How do I do this? (I've tried a lot, to no avail.)
我该怎么做呢?(我试了很多,都无济于事。)
Per a suggestion, here is the head in dict form
根据建议,这是字典形式的头部
{('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}}
采纳答案by Andy Hayden
I think the easiest way to do this would be to set the columns to the top level:
我认为最简单的方法是将列设置为顶级:
df.columns = df.columns.get_level_values(0)
Note: if the to level has a name you can also access it by this, rather than 0.
注意:如果 to 级别有名称,您也可以通过 this 访问它,而不是 0。
.
.
If you want to combine/joinyour MultiIndex into one Index (assuming you have just string entries in your columns)you could:
如果您想将joinMultiIndex组合成一个索引(假设您的列中只有字符串条目),您可以:
df.columns = [' '.join(col).strip() for col in df.columns.values]
Note: we must stripthe whitespace for when there is no second index.
注意: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']
回答by Zelazny7
And if you want to retain any of the aggregation info from the second level of the multiindex you can try this:
如果您想保留多索引第二级的任何聚合信息,您可以尝试以下操作:
In [1]: new_cols = [''.join(t) for t in df.columns]
Out[1]:
['USAF',
'WBAN',
'day',
'month',
's_CDsum',
's_CLsum',
's_CNTsum',
's_PCsum',
'tempfamax',
'tempfamin',
'year']
In [2]: df.columns = new_cols
回答by Theodros Zelleke
Andy Hayden's answer is certainly the easiest way -- if you want to avoid duplicate column labels you need to tweak a bit
安迪海登的答案当然是最简单的方法——如果你想避免重复的列标签,你需要稍微调整一下
In [34]: df
Out[34]:
USAF WBAN day month s_CD s_CL s_CNT s_PC tempf year
sum sum sum sum amax amin
0 702730 26451 1 1 12 0 13 1 30.92 24.98 1993
1 702730 26451 2 1 13 0 13 0 32.00 24.98 1993
2 702730 26451 3 1 2 10 13 1 23.00 6.98 1993
3 702730 26451 4 1 12 0 13 1 10.04 3.92 1993
4 702730 26451 5 1 10 0 13 3 19.94 10.94 1993
In [35]: mi = df.columns
In [36]: mi
Out[36]:
MultiIndex
[(USAF, ), (WBAN, ), (day, ), (month, ), (s_CD, sum), (s_CL, sum), (s_CNT, sum), (s_PC, sum), (tempf, amax), (tempf, amin), (year, )]
In [37]: mi.tolist()
Out[37]:
[('USAF', ''),
('WBAN', ''),
('day', ''),
('month', ''),
('s_CD', 'sum'),
('s_CL', 'sum'),
('s_CNT', 'sum'),
('s_PC', 'sum'),
('tempf', 'amax'),
('tempf', 'amin'),
('year', '')]
In [38]: ind = pd.Index([e[0] + e[1] for e in mi.tolist()])
In [39]: ind
Out[39]: Index([USAF, WBAN, day, month, s_CDsum, s_CLsum, s_CNTsum, s_PCsum, tempfamax, tempfamin, year], dtype=object)
In [40]: df.columns = ind
In [46]: df
Out[46]:?
? ? ?USAF ? WBAN ?day ?month ?s_CDsum ?s_CLsum ?s_CNTsum ?s_PCsum ?tempfamax ?tempfamin ?\
0 ?702730 ?26451 ? ?1 ? ? ?1 ? ? ? 12 ? ? ? ?0 ? ? ? ?13 ? ? ? ?1 ? ? ?30.92 ? ? ?24.98 ??
1 ?702730 ?26451 ? ?2 ? ? ?1 ? ? ? 13 ? ? ? ?0 ? ? ? ?13 ? ? ? ?0 ? ? ?32.00 ? ? ?24.98 ??
2 ?702730 ?26451 ? ?3 ? ? ?1 ? ? ? ?2 ? ? ? 10 ? ? ? ?13 ? ? ? ?1 ? ? ?23.00 ? ? ? 6.98 ??
3 ?702730 ?26451 ? ?4 ? ? ?1 ? ? ? 12 ? ? ? ?0 ? ? ? ?13 ? ? ? ?1 ? ? ?10.04 ? ? ? 3.92 ??
4 ?702730 ?26451 ? ?5 ? ? ?1 ? ? ? 10 ? ? ? ?0 ? ? ? ?13 ? ? ? ?3 ? ? ?19.94 ? ? ?10.94 ??
? ?year ?
0 ?1993 ?
1 ?1993 ?
2 ?1993 ?
3 ?1993 ?
4 ?1993
回答by agartland
In case you want to have a separator in the name between levels, this function works well.
如果您想在级别之间的名称中使用分隔符,则此功能效果很好。
def flattenHierarchicalCol(col,sep = '_'):
if not type(col) is tuple:
return col
else:
new_col = ''
for leveli,level in enumerate(col):
if not level == '':
if not leveli == 0:
new_col += sep
new_col += level
return new_col
df.columns = df.columns.map(flattenHierarchicalCol)
回答by Gleb Yarnykh
pd.DataFrame(df.to_records()) # multiindex become columns and new index is integers only
回答by Holy cow
You could also do as below. Consider dfto be your dataframe and assume a two level index (as is the case in your example)
你也可以做如下。考虑df作为您的数据框并假设一个两级索引(就像您的示例中的情况一样)
df.columns = [(df.columns[i][0])+'_'+(datadf_pos4.columns[i][1]) for i in range(len(df.columns))]
回答by Niels
A bit late maybe, but if you are not worried about duplicate column names:
可能有点晚了,但如果您不担心重复的列名:
df.columns = df.columns.tolist()
回答by tvt173
df.columns = ['_'.join(tup).rstrip('_') for tup in df.columns.values]
回答by jxstanford
A general solution that handles multiple levels and mixed types:
处理多层次和混合类型的通用解决方案:
df.columns = ['_'.join(tuple(map(str, t))) for t in df.columns.values]
回答by Nolan Conaway
Following @jxstanford and @tvt173, I wrote a quick function which should do the trick, regardless of string/int column names:
在@jxstanford 和@tvt173 之后,我编写了一个快速函数,无论字符串/整数列名如何,它都应该可以解决问题:
def flatten_cols(df):
df.columns = [
'_'.join(tuple(map(str, t))).rstrip('_')
for t in df.columns.values
]
return df

