将 MultiIndex DataFrame 格式从列排序到 Pandas 中的变量
Sorting MultiIndex DataFrame format from columns to variables in Pandas
我有这个 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
它是一个多索引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
列都是 merged/stacked 在一个新列 x_new
下,以及 y
列在 y_new
列下。 x
值始终应采用相同原始和列的 y
值。
这是我尝试做的:
先,我加入列索引后就用了melt()
,变成单索引'_'.join(col).strip()
它创建了额外的错误行。这些错误的行有错误的值,例如:Age_x
和 Hgt_y
在同一行。
永远记住,例如:Age_x
和 Age_y
在同一行。或者,Hgt_x
和 Hgt_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
我不知道我还能做什么。
有没有办法使用简单的 pandas
代码将 MultiIndex DataFrame
转换为我正在寻找的 最终结果?
只需指定两次stack
level=0
instead of the default (level=-1
) (droplevel
is used to remove the unneeded index level instead of 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
添加sort_index
to order lexicographically before reset_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_axis
and add_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
另一种方法,使用 stack/unstack,因为它隐式地对级别进行排序:
(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]
})
另一种选择是列表理解,然后是串联(速度方面,我希望@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
我有这个 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
它是一个多索引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
列都是 merged/stacked 在一个新列 x_new
下,以及 y
列在 y_new
列下。 x
值始终应采用相同原始和列的 y
值。
这是我尝试做的:
先,我加入列索引后就用了melt()
,变成单索引'_'.join(col).strip()
它创建了额外的错误行。这些错误的行有错误的值,例如:Age_x
和 Hgt_y
在同一行。
永远记住,例如:Age_x
和 Age_y
在同一行。或者,Hgt_x
和 Hgt_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
我不知道我还能做什么。
有没有办法使用简单的 pandas
代码将 MultiIndex DataFrame
转换为我正在寻找的 最终结果?
只需指定两次stack
level=0
instead of the default (level=-1
) (droplevel
is used to remove the unneeded index level instead of 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
添加sort_index
to order lexicographically before reset_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_axis
and add_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
另一种方法,使用 stack/unstack,因为它隐式地对级别进行排序:
(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]
})
另一种选择是列表理解,然后是串联(速度方面,我希望@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