Python Pandas – 如何在列中拼合分层索引

我有一个在轴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 

我想扁平它,所以它看起来像这样(名字不重要 – 我可以重命名):

  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 

我该怎么做呢? (我试了很多,没有用。)

根据build议,这里是字典forms的头

 {('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}} 

我认为最简单的方法是将列设置为顶层:

 df.columns = df.columns.get_level_values(0) 

注意:如果to级别有一个名字,你也可以通过它访问它,而不是0。

如果您想将MultiIndex组合/ join一个索引(假设您的列中只有string条目),您可以:

 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'] 
 pd.DataFrame(df.to_records()) # multiindex become columns and new index is integers only 

安迪·海登的答案当然是最简单的方法 – 如果你想避免重复的列标签,你需要调整一下

 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 

如果你想保留multiindex的第二级的任何聚合信息,你可以试试这个:

 In [1]: [''.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 

如果你想在级别名称中有一个分隔符,这个函数运行良好。

 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) 
 df.columns = ['_'.join(tup).rstrip('_') for tup in df.columns.values] 

也许有点晚,但是如果你不担心重复的列名:

 df.columns = df.columns.tolist() 

处理多个级别和混合types的一般解决scheme:

 df.columns = ['_'.join(tuple(map(str, t))) for t in df.columns.values] 

在@jxstanford和@ tvt173之后,我写了一个快速的函数,不pipestring / int列的名字如何,都应该这样做:

 def flatten_cols(df): df.columns = [ '_'.join(tuple(map(str, t))).rstrip('_') for t in df.columns.values ] return df 

你也可以做如下。 考虑df是你的数据框,并假设一个两级索引(如在你的例子中的情况)

 df.columns = [(df.columns[i][0])+'_'+(datadf_pos4.columns[i][1]) for i in range(len(df.columns))]