为什么pd.MultiIndex.from_tuples更改元组的顺序

时间:2019-01-18 16:03:39

标签: python pandas dataframe

使用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

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

请注意,这存在性能问题,因为期望对索引进行排序以进行快速查找