使用from_tuples创建多索引时,创建索引对象的顺序与输入元组的顺序不同
我正在尝试使用pd.MultiIndex.from_tuples方法向数据框添加列级别,但是该级别与我期望的有所不同。
df = pd.DataFrame({'x_1':[1, 2], 'x_2':[3, 4], 'x_10':[3, 4], 'y_1':[5, 6], 'y_2':[7, 8], 'y_10':[1, 2]})
df = df.reindex(columns=['x_1', 'x_2', 'x_10', 'y_1', 'y_2', 'y_10'])
index = pd.MultiIndex.from_tuples([tuple(c.split('_')) for c in df.columns])
print(index)
MultiIndex(levels=[['x', 'y'], ['1', '10', '2']],
labels=[[0, 0, 0, 1, 1, 1], [0, 2, 1, 0, 2, 1]])
当我将级别添加到数据帧并执行堆叠时,顺序不是我想要的。
df.columns = index
df.stack()
x y
0 1 1 5
10 3 1
2 3 7
1 1 2 6
10 4 2
2 4 8
我希望索引水平如下:
MultiIndex(levels=[['x', 'y'], ['1', '2', '10']])
和堆叠如下所示:
df.stack()
x y
0 1 1 5
2 3 7
10 3 1
1 1 2 6
2 4 8
10 4 2
答案 0 :(得分:1)
您构造的索引实际上是按指定顺序排序的。当您print(index)
时,您会看到Pandas如何在内部存储索引 。使用index.values
可以解开此表示形式,以给出与数据框对齐的索引数组。
print(index.values)
# array([('x', '1'), ('x', '2'), ('x', '10'), ('y', '1'), ('y', '2'),
# ('y', '10')], dtype=object)
df.columns = index
print(df)
# x y
# 1 2 10 1 2 10
# 0 1 3 3 5 7 1
# 1 2 4 4 6 8 2
真正的问题是pd.DataFrame.stack
应用排序,并且由于定义了字符串,因此'10'
在'2'
之前。要根据需要在之后 stack
保持顺序,请确保使用整数:
def splitter(x):
strng, num = x.split('_')
return strng, int(num)
index = pd.MultiIndex.from_tuples(df.columns.map(splitter))
df.columns = index
print(df.stack())
# x y
# 0 1 1 5
# 2 3 7
# 10 3 1
# 1 1 2 6
# 2 4 8
# 10 4 2
答案 1 :(得分:1)
您可以reindex
处于特定级别,将调用前列中的级别值传递给stack
:
In[177]:
df.stack().reindex(df.columns.get_level_values(1).unique(), level=1)
Out[177]:
x y
0 1 1 5
2 3 7
10 3 1
1 1 2 6
2 4 8
10 4 2
请注意,这存在性能问题,因为期望对索引进行排序以进行快速查找