【问题标题】:pd.Series assignment with pd.IndexSlice results in NaN values despite matching indicespd.Series 分配与 pd.IndexSlice 导致 NaN 值,尽管匹配索引
【发布时间】:2020-01-20 17:35:34
【问题描述】:

我有一个多索引系列如下。

> data = [['a', 'X', 'u', 1], ['a', 'X', 'v', 2], ['b', 'Y', 'u', 4], ['a', 'Z', 'u', 20]]
> s = pd.DataFrame(data, columns='one two three four'.split()).set_index('one two three'.split()).four
> s
one  two  three
a    X    u         1
          v         2
b    Y    u         4
a    Z    u        20
Name: four, dtype: int64

然后是第二个系列,只有 onethree 作为索引:

>>> data2 = [['a', 'u', 3], ['a', 'v', -3]]
>>> s2 = pd.DataFrame(data2, columns='one three four'.split()).set_index('one three'.split()).four
>>> s2
one  three
a    u        3
     v       -3
Name: four, dtype: int64

所以,据我所知,s2s.loc[pd.IndexSlice[:, 'X', :]] 的索引相同。

因此,我希望能够做到:

>>> s.loc[pd.IndexSlice[:, 'X', :]] = s2

但这样做会产生NaN 值:

>>> s
one  two  three
a    X    u         NaN
          v         NaN
b    Y    u         4.0
a    Z    u        20.0
Name: four, dtype: float64

这样做的正确方法是什么?

【问题讨论】:

  • 为什么评论者删除了 s2.values 评论?
  • @ScottBoston 索引对齐。
  • @QuangHoang 真...真的。
  • 索引对齐可以通过sort_index 解决。但我想这不是问题的重点。

标签: python pandas multi-index


【解决方案1】:

pandas MultiIndexes 有时有点错误,这感觉就像是其中一种情况。如果您修改 s2.index 以匹配 s.index,则分配有效:

In [155]: s2.index = pd.MultiIndex.from_product([['a'], ['X'], ['u', 'v']], names=['one', 'two', 'three'])

In [156]: s2
Out[156]:
one  two  three
a    X    u        3
          v       -3
Name: four, dtype: int64

In [157]: s
Out[157]:
one  two  three
a    X    u         1
          v         2
b    Y    u         4
a    Z    u        20
Name: four, dtype: int64

In [158]: s.loc[:, 'X', :] = s2

In [159]: s
Out[159]:
one  two  three
a    X    u         3
          v        -3
b    Y    u         4
a    Z    u        20
Name: four, dtype: int64

可能值得在https://github.com/pandas-dev/pandas/issues 中搜索类似的问题,如果还没有,则将其添加为新问题。

与此同时,另一种选择是使用.unstack() 重塑您的数据以完成分配:

In [181]: s = s.unstack('two')

In [182]: s['X'].loc[s2.index] = s2

In [183]: s.stack().swaplevel(1,2).sort_index()
Out[183]:
one  two  three
a    X    u         3.0
          v        -3.0
     Z    u        20.0
b    Y    u         4.0
dtype: float64

【讨论】:

  • 感谢这些变通方法看起来不错。如果我找不到重复项,稍后会提交错误。
  • 另外,我的实际索引有更多的值,所以我不想写出产品。我找到了另一个question,它给了我一个将级别添加到s2的索引的好方法:s2 = pd.concat({'X': s2}, names=['two']).swaplevel(0, 1)
【解决方案2】:

作为@randy 答案的替代方案,您可以将s2 转换为列表,因此您不必关心索引匹配(但它不会像join 而只是一个分配保留顺序双方):

>>> s.loc[pd.IndexSlice[:, 'X', :]]=s2.to_list()
>>> s
one  two  three
a    X    u         3.0
          v        -3.0
b    Y    u         4.0
a    Z    u        20.0
Name: four, dtype: float64

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2018-07-24
    • 2017-08-29
    相关资源
    最近更新 更多