【问题标题】:How to avoid sorting when indexing Pandas MultiIndex?索引 Pandas MultiIndex 时如何避免排序?
【发布时间】:2019-06-13 03:54:18
【问题描述】:

当按第二级索引具有两级的 MultiIndexed pandas 数据帧时,结果会自动按索引排序。有没有一种不用排序就可以得到结果的优雅方法?

这是一个玩具示例:

>>> df = pd.DataFrame(np.ones((10, 3)), columns=list("ABC"))
>>> df.index = pd.MultiIndex.from_product([range(5), list("AB")])
>>> df
       A    B    C
0 A  1.0  1.0  1.0
  B  1.0  1.0  1.0
1 A  1.0  1.0  1.0
  B  1.0  1.0  1.0
2 A  1.0  1.0  1.0
  B  1.0  1.0  1.0
3 A  1.0  1.0  1.0
  B  1.0  1.0  1.0
4 A  1.0  1.0  1.0
  B  1.0  1.0  1.0

>>> values = ["B", "A"]
>>> idx = pd.IndexSlice
>>> subset = df.loc[idx[:, values], values]
>>> subset
       B    A
0 A  1.0  1.0
  B  1.0  1.0
1 A  1.0  1.0
  B  1.0  1.0
2 A  1.0  1.0
  B  1.0  1.0
3 A  1.0  1.0
  B  1.0  1.0
4 A  1.0  1.0
  B  1.0  1.0

我本来希望结果索引的第二级按["B", "A"] 的顺序排列——类似于选定的列——但它是按排序顺序返回的。

到目前为止,我发现的解决方法是使用 subset.reindex(index=values, level=1) 重新索引结果。有没有办法以更简洁/优雅的方式做到这一点,理想情况下不会导致数据帧的副本?为什么首先对结果进行排序?在这种情况下似乎不直观。

【问题讨论】:

    标签: python pandas multi-index


    【解决方案1】:

    这可能是为了性能而做出的决定。您可以在 Sorting a MultiIndex 中阅读有关它的内容,外卖是您希望对索引进行 lexsorted,它由 .loc 的当前输出维护。如果它为您提供了您想要的输出,则索引不会被 lexsorted,这可能会导致几个问题。你应该使用.reindex,因为它会导致一个lexsorted MultiIndex


    您原来的 DataFrame 是 lexsorted:

    df.index.is_lexsorted()
    #True
    

    你得到的 unwanted 输出维持了排序:

    df.loc[idx[:, values], values].index.is_lexsorted()
    #True
    

    如果我们使用.loc 修改了排序,我们将失去这种排序,并且现在根据文档会遇到性能问题。

    subset = df.loc[[(0, 'B'), (0, 'A')], ['B', 'A']]
    #       B    A
    #0 B  1.0  1.0
    #  A  1.0  1.0
    
    subset.index.is_lexsorted()
    #False
    

    虽然重新索引确实需要更长的时间,但它会导致一个 lexsorted 索引。

    subset2 = df.reindex(index=values, level=1)
    subset2.index.is_lexsorted()
    #True
    

    当您的 MultiIndex 未进行 lexsorted 时,会有意想不到的后果。因此,即使subset 似乎已排序并且应该可以对范围进行切片,但您不能。在.reindex 之后,切片是可行的,因为它是 lexsorted:

    subset.loc[(0,'B'): (0, 'A')]
    #UnsortedIndexError: 'Key length (2) was greater than MultiIndex lexsort depth (1)'
    
    subset2.loc[(0,'B'): (0, 'A')]
    #       A    B    C
    #0 B  1.0  1.0  1.0
    #  A  1.0  1.0  1.0
    

    【讨论】:

    • 谢谢,这是有道理的(尽管我仍然觉得结果不直观)。在我的用例中,这实际上是滚动协方差矩阵的数据框,因此保持每个协方差矩阵的对称性质(其中行和列具有相同的顺序)很重要。我想我现在会坚持重新索引。
    猜你喜欢
    • 2013-02-20
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 2023-03-10
    • 2016-05-12
    • 2018-12-29
    • 2016-04-08
    相关资源
    最近更新 更多