将 MultiIndex DataFrame 格式从列排序到 Pandas 中的变量

Posted

技术标签:

【中文标题】将 MultiIndex DataFrame 格式从列排序到 Pandas 中的变量【英文标题】:Sorting MultiIndex DataFrame format from columns to variables in Pandas 【发布时间】:2022-01-21 17:17:12 【问题描述】:

我有这个DataFrame

      Age         Hgt         Wgt     
      x     y     x     y     x     y
0     26    24    160   164   95    71
1     35    37    182   163   110   68
2     57    52    175   167   89    65

它是一个 MultiIndex DataFrame

我正在使用pandas 来获得这个最终结果

      x_new    y_new    parameter     
0     26       24       Age
1     35       37       Age  
2     57       52       Age
3     160      164      Hgt           
4     182      163      Hgt             
5     175      167      Hgt              
6     95       71       Wgt     
7     110      68       Wgt     
8     89       65       Wgt     

基本上,所有x 列都合并/堆叠在一个新列x_new 下,y 列在y_new 列下。 x 值始终应采用相同原始和列的 y 值。

这是我尝试做的:

首先,加入列索引后,我使用melt()成为单索引'_'.join(col).strip() 它创建了额外的错误行。这些错误的行具有错误的值,例如:Age_xHgt_y 在同一行中。 请记住,例如:Age_xAge_y 在同一行中。或者,Hgt_xHgt_y 在同一行。

第二,我用stack(),它给了我这样的结果:

df.stack().reset_index(level=0, drop=True).reset_index()
      index    Age      Hgt      Wgt
0     x        26       160      95
1     y        24       164      71  
2     x        35       182      110
3     y        37       163      68
4     x        57       175      89
5     y        52       167      65    

我不知道我还能做什么。

有没有办法使用简单的pandascode 将 MultiIndex DataFrame 转换为我正在寻找的最终结果

【问题讨论】:

【参考方案1】:

只需指定stacklevel=0而不是默认的(level=-1)(droplevel用于删除不需要的索引级别而不是reset_index两次):

df.stack(level=0).droplevel(0).reset_index()

  index    x    y
0   Age   26   24
1   Hgt  160  164
2   Wgt   95   71
3   Age   35   37
4   Hgt  182  163
5   Wgt  110   68
6   Age   57   52
7   Hgt  175  167
8   Wgt   89   65

reset_index之前添加sort_index以按字典顺序排列:

df.stack(level=0).droplevel(0).sort_index().reset_index()

  index    x    y
0   Age   26   24
1   Age   35   37
2   Age   57   52
3   Hgt  160  164
4   Hgt  182  163
5   Hgt  175  167
6   Wgt   95   71
7   Wgt  110   68
8   Wgt   89   65

我们可以通过rename_axisadd_suffix进一步清理输出以添加更改索引名称并将'_new'后缀添加到'x'和'y'列:

(df.stack(level=0) 
   .droplevel(0)
   .sort_index() 
   .add_suffix('_new')
   .rename_axis(index='parameter') 
   .reset_index()
)

  parameter  x_new  y_new
0       Age     26     24
1       Age     35     37
2       Age     57     52
3       Hgt    160    164
4       Hgt    182    163
5       Hgt    175    167
6       Wgt     95     71
7       Wgt    110     68
8       Wgt     89     65

另一种方式,使用堆栈/取消堆栈,因为它隐式地对级别进行排序:

(df
.T
.unstack(1)
.stack(0)
.droplevel(1)
.rename_axis('parameter')
.add_suffix('_new')
.reset_index()
)

使用的设置:

import pandas as pd

df = pd.DataFrame(
    ('Age', 'x'): [26, 35, 57], ('Age', 'y'): [24, 37, 52],
    ('Hgt', 'x'): [160, 182, 175], ('Hgt', 'y'): [164, 163, 167],
    ('Wgt', 'x'): [95, 110, 89], ('Wgt', 'y'): [71, 68, 65]
)

【讨论】:

【参考方案2】:

另一个选项是列表推导,然后是串联(在速度方面,我希望@HenryEcker 的解决方案性能更高,在测试之前你永远不会知道,只有在你热衷于性能时才进行测试) :

pd.concat([df[key].add_suffix('_new')
                  .assign(parameter=key) 
           for key in df.columns.levels[0]], 
          ignore_index=True,
          sort = False,
          copy = False)

   x_new  y_new parameter
0     26     24       Age
1     35     37       Age
2     57     52       Age
3    160    164       Hgt
4    182    163       Hgt
5    175    167       Hgt
6     95     71       Wgt
7    110     68       Wgt
8     89     65       Wgt

【讨论】:

以上是关于将 MultiIndex DataFrame 格式从列排序到 Pandas 中的变量的主要内容,如果未能解决你的问题,请参考以下文章

pandas:将两个 DataFrame 与已排序的 MultiIndex 连接起来,使得结果具有已排序的 MultiIndex

将 DataFrame 列拆分为两个 + MultiIndex

Pandas - 将 DataFrame 值除以 MultiIndex DataFrame 中的系列

将 DataFrame 列分组为 MultiIndex 的功能方法

Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接,以及自定义排序

将 json 读取为 Multiindex DataFrame