【发布时间】:2018-10-10 10:14:27
【问题描述】:
正如我在this partially related question 中指出的,不再可以对混合类型的序列进行排序:
# Python3.6
sorted(['foo', 'bar', 10, 200, 3])
# => TypeError: '<' not supported between instances of 'str' and 'int'
这会影响 pandas 中的切片查询。下面的例子说明了我的问题。
import pandas as pd
import numpy as np
index = [(10,3),(10,1),(2,2),('foo',4),('bar',5)]
index = pd.MultiIndex.from_tuples(index)
data = np.random.randn(len(index),2)
table = pd.DataFrame(data=data, index=index)
idx=pd.IndexSlice
table.loc[idx[:10,:],:]
# The last line will raise an UnsortedIndexError because
# 'foo' and 'bar' appear in the wrong order.
异常信息如下:
UnsortedIndexError: 'MultiIndex slicing requires the index to be lexsorted: slicing on levels [0], lexsort depth 0'
在 python2.x 中,我通过对索引进行 lex-sorting 来从这个异常中恢复:
# Python2.x:
table = table.sort_index()
# 0 1
# 2 2 0.020841 0.717178
# 10 1 1.608883 0.807834
# 3 0.566967 1.978718
# bar 5 -0.683814 -0.382024
# foo 4 0.150284 -0.750709
table.loc[idx[:10,:],:]
# 0 1
# 2 2 0.020841 0.717178
# 10 1 1.608883 0.807834
# 3 0.566967 1.978718
但是,在 python3 中,我最终遇到了我在开头提到的异常:
TypeError: '<' not supported between instances of 'str' and 'int'
如何从中恢复?在排序之前将索引转换为字符串不是一种选择,因为这会破坏索引的正确排序:
# Python2/3
index = [(10,3),(10,1),(2,2),('foo',4),('bar',5)]
index = list(map(lambda x: tuple(map(str,x)), index))
index = pd.MultiIndex.from_tuples(index)
data = np.random.randn(len(index),2)
table = pd.DataFrame(data=data, index=index)
table = table.sort_index()
# 0 1
# 10 1 0.020841 0.717178
# 3 1.608883 0.807834
# 2 2 0.566967 1.978718
# bar 5 -0.683814 -0.382024
# foo 4 0.150284 -0.750709
使用此排序,基于值的切片将被破坏。
table.loc[idx[:10,:],:] # Raises a TypeError
table.loc[idx[:'10',:],:] # Misses to return the indices [2,:]
我该如何从中恢复?
【问题讨论】:
-
如果您只想要字典排序(这与 Python 2 的排序行为不相同),那么只需将所有内容排序为字符串
sorted(['foo', 'bar', 10, 200, 3], key=str) -
@Chris_Rands 我在问题中提到这对我不起作用,因为像 [:200] 这样的索引不起作用。
-
注意:我也为此发布了issue on pandas-dev。
标签: python python-3.x pandas sorting