为啥在具有一级索引的 MultiIndex 列的 pandas DataFrame 中表现不同?

Posted

技术标签:

【中文标题】为啥在具有一级索引的 MultiIndex 列的 pandas DataFrame 中表现不同?【英文标题】:Why in a pandas DataFrame with a MultiIndex columns of one level indexing behaves differently?为什么在具有一级索引的 MultiIndex 列的 pandas DataFrame 中表现不同? 【发布时间】:2020-11-25 00:05:51 【问题描述】:

使用来自pandas 文档的示例here,以下索引完美运行,结果为pd.Series

import pandas as pd
tuples = [(1, 'red'), (1, 'blue'),
          (2, 'red'), (2, 'blue')]
columns = pd.MultiIndex.from_tuples(tuples, names=('number', 'color'))
asdf = pd.DataFrame(columns=columns, index=[0, 1])
asdf.loc[:, (1, 'red')]

但是如果我稍微改一下代码,去掉一层,同样的索引就不行了:

import pandas as pd
tuples = [(1,), (2,)]
columns = pd.MultiIndex.from_tuples(tuples, names=['number'])
asdf = pd.DataFrame(columns=columns, index=[0, 1])
asdf.loc[:, (1,)]

IndexError                                Traceback (most recent call last)
<ipython-input-43-d55399a979fa> in <module>
----> 1 asdf.loc[:, (1,)]

/opt/conda/lib/python3.8/site-packages/pandas/core/indexing.py in __getitem__(self, key)
   1760                 except (KeyError, IndexError, AttributeError):
   1761                     pass
-> 1762             return self._getitem_tuple(key)
   1763         else:
   1764             # we by definition only have the 0th axis

/opt/conda/lib/python3.8/site-packages/pandas/core/indexing.py in _getitem_tuple(self, tup)
   1270     def _getitem_tuple(self, tup: Tuple):
   1271         try:
-> 1272             return self._getitem_lowerdim(tup)
   1273         except IndexingError:
   1274             pass

/opt/conda/lib/python3.8/site-packages/pandas/core/indexing.py in _getitem_lowerdim(self, tup)
   1371         # we may have a nested tuples indexer here
   1372         if self._is_nested_tuple_indexer(tup):
-> 1373             return self._getitem_nested_tuple(tup)
   1374 
   1375         # we maybe be using a tuple to represent multiple dimensions here

/opt/conda/lib/python3.8/site-packages/pandas/core/indexing.py in _getitem_nested_tuple(self, tup)
   1451 
   1452             current_ndim = obj.ndim
-> 1453             obj = getattr(obj, self.name)._getitem_axis(key, axis=axis)
   1454             axis += 1
   1455 

/opt/conda/lib/python3.8/site-packages/pandas/core/indexing.py in _getitem_axis(self, key, axis)
   1963         # fall thru to straight lookup
   1964         self._validate_key(key, axis)
-> 1965         return self._get_label(key, axis=axis)
   1966 
   1967 

/opt/conda/lib/python3.8/site-packages/pandas/core/indexing.py in _get_label(self, label, axis)
    620             # see GH5667
    621             return self.obj._xs(label, axis=axis)
--> 622         elif isinstance(label, tuple) and isinstance(label[axis], slice):
    623             raise IndexingError("no slices here, handle elsewhere")
    624 

IndexError: tuple index out of range

此外,将其索引为asdf.loc[:, 1] 会引发TypeError,此外,将其索引为asdf.loc[:, ((1,),)] 可以,但结果是pd.DataFrame,而不是pd.Series

为什么会这样?非常感谢您!

P.S.:我有兴趣从这些问题中“抽象”我的代码(pd.DataFrame.columns 中的一个级别与多个级别)。在我工作的公司中,有时我们会在需要多个级别的情况下获取客户数据,但有时只需要一个级别。

【问题讨论】:

我不知道ng. 是什么......如果我删除ng.,两者对我的工作相同 @RobRaymond 抱歉,那是剩余代码。我刚刚编辑了我的问题。谢谢! asdf.loc[:, (1,)] 在 1.1.0 版中对我来说很好 @RichieV 是的,它工作正常!我必须更新pandas,我目前的版本是v1.0.3 【参考方案1】:

你更新你的熊猫版本了吗?在pandas v1.1.0 中,您可以像以前一样使用一级索引,切片返回pd.Series

import pandas as pd
tuples = [(1,), (2,)]
columns = pd.MultiIndex.from_tuples(tuples, names=['number'])
asdf = pd.DataFrame(columns=columns, index=[0, 1])
asdf.loc[:, (1,)]

输出:

0    NaN
1    NaN

【讨论】:

这个!这就是我一直在寻找的!谢谢!是的,我应该更新pandas,我当前的版本是v1.0.3

以上是关于为啥在具有一级索引的 MultiIndex 列的 pandas DataFrame 中表现不同?的主要内容,如果未能解决你的问题,请参考以下文章

合并两个具有重叠 MultiIndex 列的 DataFrame

按一级 MultiIndex 对 pandas DataFrame 进行排序

在日期为“关闭”的级别上重新索引 MultiIndex

对包含 str 和元组的 Pandas MultiIndex 进行排序

按特定索引值过滤具有 MultiIndex 的数据帧 [重复]

Pandas MultiIndex 中列的条件切片