pandas - 确保 Pandas MultiIndex 中的字典序排序

标签 pandas

我有一些带有 MultiIndex 的数据(一些计时统计数据,带有“设备”、“构建配置”、“测试功能”等的索引级别)。我想切出其中一些索引列。

似乎 .loc 函数的“切片器”可能是要走的路。然而docs包含此警告:

Warning: You will need to make sure that the selection axes are fully lexsorted!



稍后在文档中有一个关于 The Need for Sortedness with MultiIndex 的部分其中说

you are responsible for ensuring that things are properly sorted



但谢天谢地,

The MultiIndex object has code to explicity check the sort depth. Thus, if you try to index at a depth at which the index is not sorted, it will raise an exception.



听起来不错。

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

There is an important new method sortlevel to sort an axis within a MultiIndex so that its labels are grouped and sorted by the original ordering of the associated factor at that level. Note that this does not necessarily mean the labels will be sorted lexicographically!



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

编辑:我的探索建议了创建多索引的大多数方法在构建索引时自动对唯一标签进行词法排序。例子:
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'])

请注意 levels 数组中的唯一项是如何进行词法排序的,即使 DataFrame 对象本身不是。然后,正如预期的那样:
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

但是,如果级别是明确排序的,因此它们没有排序,事情就会变得很奇怪:
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'])

所以 sorted2 报告它是 lexsorted,而实际上它不是。这感觉有点像文档中的警告所指的内容,但仍然不清楚如何修复它或者它是否真的是一个问题。

最佳答案

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

为了检查您的索引(或列)是否已排序,他们有一个方法 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

检查 is_lexsorted 和 lexsort_depth:
In [2]: s.index.is_lexsorted()
Out[2]: False

In [3]: s.index.lexsort_depth
Out[3]: 0

对索引进行排序,并重新检查值:
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

关于pandas - 确保 Pandas MultiIndex 中的字典序排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31427466/

相关文章:

python - 如何在 Python 中融化或取消堆叠数据帧?

python - 如何使用 Pandas 查找重复名称?

python - 如何获取 Pandas 数据框中一行的百分位数?

Python 识别时间序列数据框中的美国假期

python - 如何用Python计算 Assets 的风险贡献

python - 如何删除所有重复出现或在 Pandas 数据框中获取唯一值?

python - 对于给定的 Pandas df,按列对 df 进行排序(首先是最高的求和值),然后在每个唯一值顺序中按另一列排序

python - 使用 pandas 按类别进行计算

python - 检查 pandas 中的 'None' 值时排除 'NaN'

python - 无法使用 pandas 读取 excel 文件的所有工作表