【问题标题】:A Lexicographical Bug in Pandas?Pandas 中的字典错误?
【发布时间】:2021-12-22 20:11:54
【问题描述】:

出于好奇,请您轻描淡写:

正如我试图查看 MultiIndex 中的切片是如何工作的,我遇到了以下情况 ↓

# Simple MultiIndex Creation
index = pd.MultiIndex.from_product([['a', 'c', 'b'], [1, 2]])

# Making Series with that MultiIndex
data = pd.Series(np.random.randint(10, size=6), index=index)

返回:

一个 1 5 2 0 1 8 2 6 乙 1 6 2 3 数据类型:int32

注意索引在排序顺序中不是,即。 a, c, b 是在切片时会导致 expected 错误的顺序。

# When we do slicing
data.loc["a":"c"]

类似的错误:

未排序索引错误 ----> 1 个数据.loc["a":"c"] UnsortedIndexError: '键长度 (1) 大于 MultiIndex lexsort 深度 (0)'

这是意料之中的。但是现在,在做了以下步骤之后:

# Making a DataFrame
data = data.unstack()

# Redindexing - to unsort the indices like before
data = data.reindex(["a", "c", "b"])

# Which looks like 
   1  2
a  5  0
c  8  6
b  6  3

# Then again making series
data = data.stack()

# Reindex Again!
data = data.reindex(["a", "c", "b"], level=0)


# Which looks like before
a  1    5
   2    0
c  1    8
   2    6
b  1    6
   2    3
dtype: int32

问题

所以,现在流程是:Series → Unstack → DataFrame → Stack → Series

现在,如果我像之前一样进行切片(仍然使用未排序的索引)我们不会收到任何错误!

# The same slicing
data.loc["a":"c"]

没有错误的结果:

一个 1 5 2 0 1 8 2 6 数据类型:int32

即使data.index.is_monotonicFalse。那我们为什么还要切片呢?

所以问题是:为什么?

希望您了解这里的情况。因为看到,在给出错误之前的同一系列,在unstackstack 操作之后没有给出任何错误。

那是我在这里遗漏的错误还是新概念?

谢谢!
阿尤什∞沙阿

更新: 我已经使用data.reindex() 再次取消排序。请再看一遍。

【问题讨论】:

  • stack/unstack 对数据进行隐式排序,这是 MultiIndex 喜欢的,不会给您带来任何性能问题
  • @sammywemmy 很好,对数据进行了排序——但是堆叠之后呢?我尝试了redinexing。堆栈操作后我再次对数据进行了排序,没有返回任何错误!
  • 抱歉,没听懂。您介意用新场景更新您的问题吗?
  • @sammywemmy 请考虑reindex 步骤,即使在unstack 和stack 操作之后。在堆栈和 unstack 之后取消排序。感谢您的帮助。
  • 我想我现在明白你的意思了。如果您稍微使用一下错误代码,您会注意到_lexsort_depth 属性。第一次,没有任何stack/unstack/reindex戏剧,深度为0,元组长度(Multindex值)为1,失败。但是,似乎在unstack 戏剧之后,深度现在变为2,因此不执行if 条件。不知道为什么会这样。这是一个错误吗?也许......也许你可以进一步挖掘,或者在 Pandas github 页面上提出问题?

标签: python python-3.x pandas dataframe data-analysis


【解决方案1】:

您的 2 个数据框之间的区别如下:

index = pd.MultiIndex.from_product([['a', 'c', 'b'], [1, 2]])

data = pd.Series(np.random.randint(10, size=6), index=index)

data2 = data.unstack().reindex(["a", "c", "b"]).stack()

>>> data.index.codes
FrozenList([[0, 0, 2, 2, 1, 1], [0, 1, 0, 1, 0, 1]])

>>> data2.index.codes
FrozenList([[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])

即使你的两个索引外观(值)相同,内部索引(代码)也不同。

检查this methodMultiIndex

        Create a new MultiIndex from the current to monotonically sorted
        items IN the levels. This does not actually make the entire MultiIndex
        monotonic, JUST the levels.

        The resulting MultiIndex will have the same outward
        appearance, meaning the same .values and ordering. It will also
        be .equals() to the original.

旧答案

# Making a DataFrame
data = data.unstack()

# Which looks like         # <- WRONG
   1  2                    #    1  2
a  5  0                    # a  8  0
c  8  6                    # b  4  1
b  6  3                    # c  7  6

# Then again making series
data = data.stack()

# Which looks like before  # <- WRONG
a  1    5                  # a  1    2
   2    0                  #    2    1
c  1    8                  # b  1    0
   2    6                  #    2    1
b  1    6                  # c  1    3
   2    3                  #    2    9
dtype: int32

如果要使用切片,则必须检查索引是否单调:

# Simple MultiIndex Creation
index = pd.MultiIndex.from_product([['a', 'c', 'b'], [1, 2]])

# Making Series with that MultiIndex
data = pd.Series(np.random.randint(10, size=6), index=index)

>>> data.index.is_monotonic
False

>>> data.unstack().stack().index.is_monotonic
True

>>> data.sort_index().index.is_monotonic
True

【讨论】:

  • 请看一下我的步骤:我在那里使用了.reindex(),因此索引变得未排序。我之前错过的步骤:)
  • @AayushShah。我更新了答案并发现了问题。这不是一个错误。您看到的内容与内部存储的内容之间存在差异。
  • 不错的侦探工作@Corralien。为我解锁了新知识。一旦对索引进行排序,信息就会被存储(缓存)并可能被重用。谢谢
猜你喜欢
  • 2018-08-01
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-02
相关资源
最近更新 更多