确保熊猫MultiIndex中的字典编排排序

tan*_*avo 5 pandas

我有一些带有MultiIndex的数据(一些时序统计信息,以及“设备”,“构建配置”,“测试功能”等的索引级别)。我想对其中一些索引列进行切片。

.loc函数的“切片器”似乎是可行的方法。但是文档包含以下警告:

警告:您需要确保选择轴已完全按照顺序排列!

后来在文档中有一个部分需要有序性与多指标其说

您有责任确保物品正确分类

但幸运的是,

MultiIndex对象具有用于显式检查排序深度的代码。因此,如果尝试在未对索引进行排序的深度进行索引,则会引发异常。

听起来不错。

但是,剩下的问题是如何使他们的数据正确排序以使索引正常工作?文档讨论了一种重要的新方法,sortlevel()但随后包含以下警告:

有一个重要的新方法sortlevel可以对MultiIndex中的轴进行排序,以便按该级别上关联因子的原始顺序对标签进行分组和排序。请注意,这并不一定意味着标签将按字典顺序排序!

在我的情况下,sortlevel()做对了,但是如果我的“相关因子的原始排序”没有排序怎么办?是否可以在任何MultiIndex-ed DataFrame上使用一个简单的单行代码,以确保它已准备好进行切片和完全按词法排序?


编辑:我的探索建议,大多数创建MultiIndex的方法都会在建立索引时自动对唯一标签进行lexsort。例:

In [1]: 
import pandas as pd
df = pd.DataFrame({'col1': ['b','d','b','a'], 'col2': [3,1,1,2],
                  'data':['one','two','three','four']})
df

Out[1]: 
  col1  col2   data
0    b     3    one
1    d     1    two
2    b     1  three
3    a     2   four

In [2]:
df2 = df.set_index(['col1','col2'])
df2

Out[2]: 
            data
col1 col2       
b    3       one
d    1       two
b    1     three
a    2      four

In [3]: df2.index
Out[3]: 
MultiIndex(levels=[[u'a', u'b', u'd'], [1, 2, 3]],
           labels=[[1, 2, 1, 0], [2, 0, 0, 1]],
           names=[u'col1', u'col2'])
Run Code Online (Sandbox Code Playgroud)

请注意,即使DataFrame对象本身不是,也对levels数组中的唯一项进行了分类。然后,按预期方式:

In [4]: df2.index.is_lexsorted()
Out[4]: False

In [5]: 
sorted = df2.sortlevel()
sorted
Out[5]: 
            data
col1 col2       
a    2      four
b    1     three
     3       one
d    1       two

In [6]: sorted.index.is_lexsorted()
Out[6]: True
Run Code Online (Sandbox Code Playgroud)

但是,如果对级别进行了显式排序,则未对它们进行排序,那么事情就会变得很奇怪:

In [7]:
df3 = df2
df3.index.set_levels(['b','d','a'], level='col1', inplace=True)
df3.index.set_labels([0,1,0,2], level='col1', inplace=True)
df3

Out[7]: 
            data
col1 col2       
b    3       one
d    1       two
b    1     three
a    2      four

In [8]:
sorted2 = df3.sortlevel()
sorted2

Out[8]: 
            data
col1 col2       
b    1     three
     3       one
d    1       two
a    2      four

In [9]: sorted2.index.is_lexsorted()
Out[9]: True

In [10]: sorted2.index
Out[10]: 
MultiIndex(levels=[[u'b', u'd', u'a'], [1, 2, 3]],
           labels=[[0, 0, 1, 2], [0, 2, 0, 1]],
           names=[u'col1', u'col2'])
Run Code Online (Sandbox Code Playgroud)

因此sorted2报告它是按词法排序的,而实际上不是。这听起来有点像文档中的警告内容,但是仍然不清楚如何解决它,或者它是否真的是一个问题。

Jul*_*rec 1

至于排序,正如 @EdChum 指出的那样,这里的文档似乎表明它是按字典顺序排序的。

为了检查您的索引(或列)是否已排序,它们有一个方法is_lexsorted()和一个属性lexsort_depth(由于某种原因您无法在文档本身中找到)。

例子:

创建随机顺序的系列

In [1]:
import pandas as pd
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
            ['one', 'two', '1', '3', 'one', 'two', 'one', 'two']]

tuples = list(zip(*arrays))
import random; random.shuffle(tuples)
s = pd.Series(np.random.randn(8), index=pd.MultiIndex.from_tuples(tuples))
s

Out[1]:
baz  3     -0.191653
qux  two   -1.410311
bar  one   -0.336475
qux  one   -1.192908
foo  two    0.486401
baz  1      0.888314
foo  one   -1.504816
bar  two    0.917460
dtype: float64
Run Code Online (Sandbox Code Playgroud)

检查 is_lexsorted 和 lexsort_深度:

In [2]: s.index.is_lexsorted()
Out[2]: False

In [3]: s.index.lexsort_depth
Out[3]: 0
Run Code Online (Sandbox Code Playgroud)

对索引进行排序,然后重新检查值:

In [4]: s = s.sortlevel(0, sort_remaining=True)
        s

Out[4]:
bar  one   -0.336475
     two    0.917460
baz  1      0.888314
     3     -0.191653
foo  one   -1.504816
     two    0.486401
qux  one   -1.192908
     two   -1.410311
dtype: float64

In [5]: s.index.is_lexsorted()
Out[5]: True

In [6]: s.index.lexsort_depth  
Out[6]: 2
Run Code Online (Sandbox Code Playgroud)