带数据帧的“索引器太多”。

2024-05-15 05:53:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经读了一百万遍了,但是我从来没有想过,所以我仍然在想如何使用loc来用MultiIndex切分DataFrame

我将从this SO answer中的DataFrame开始:

                           value
first second third fourth       
A0    B0     C1    D0          2
                   D1          3
             C2    D0          6
                   D1          7
      B1     C1    D0         10
                   D1         11
             C2    D0         14
                   D1         15
A1    B0     C1    D0         18
                   D1         19
             C2    D0         22
                   D1         23
      B1     C1    D0         26
                   D1         27
             C2    D0         30
                   D1         31
A2    B0     C1    D0         34
                   D1         35
             C2    D0         38
                   D1         39
      B1     C1    D0         42
                   D1         43
             C2    D0         46
                   D1         47
A3    B0     C1    D0         50
                   D1         51
             C2    D0         54
                   D1         55
      B1     C1    D0         58
                   D1         59
             C2    D0         62
                   D1         63

要只选择A0C1值,我可以:

In [26]: df.loc['A0', :, 'C1', :]
Out[26]: 
                           value
first second third fourth       
A0    B0     C1    D0          2
                   D1          3
      B1     C1    D0         10
                   D1         11

它还可以从三个级别中进行选择,甚至可以使用元组:

In [28]: df.loc['A0', :, ('C1', 'C2'), 'D1']
Out[28]: 
                           value
first second third fourth       
A0    B0     C1    D1          3
             C2    D1          5
      B1     C1    D1         11
             C2    D1         13

到目前为止,直觉和才华横溢。

为什么我不能从第一个索引级别中选择所有值?

In [30]: df.loc[:, :, 'C1', :]
---------------------------------------------------------------------------
IndexingError                             Traceback (most recent call last)
<ipython-input-30-57b56108d941> in <module>()
----> 1 df.loc[:, :, 'C1', :]

/usr/local/lib/python2.7/dist-packages/pandas/core/indexing.pyc in __getitem__(self, key)
   1176     def __getitem__(self, key):
   1177         if type(key) is tuple:
-> 1178             return self._getitem_tuple(key)
   1179         else:
   1180             return self._getitem_axis(key, axis=0)

/usr/local/lib/python2.7/dist-packages/pandas/core/indexing.pyc in _getitem_tuple(self, tup)
    694 
    695         # no multi-index, so validate all of the indexers
--> 696         self._has_valid_tuple(tup)
    697 
    698         # ugly hack for GH #836

/usr/local/lib/python2.7/dist-packages/pandas/core/indexing.pyc in _has_valid_tuple(self, key)
    125         for i, k in enumerate(key):
    126             if i >= self.obj.ndim:
--> 127                 raise IndexingError('Too many indexers')
    128             if not self._has_valid_type(k, i):
    129                 raise ValueError("Location based indexing can only have [%s] "

IndexingError: Too many indexers

这当然不是故意的行为吗?

注意:我知道这在df.xs('C1', level='third')中是可能的,但是当前的.loc行为似乎不一致。


Tags: keyinselfdfb0a0locb1
2条回答

为了安全(从某种意义上说:这在所有情况下都有效),您需要对行索引和列进行索引,您可以使用pd.IndexSlice轻松地执行此操作:

In [26]: idx = pd.IndexSlice

In [27]: df.loc[idx[:, :, 'C1', :],:]
Out[27]:
                           value
first second third fourth
A0    B0     C1    D0          2
                   D1          3
      B1     C1    D0         10
                   D1         11
A1    B0     C1    D0         18
                   D1         19
      B1     C1    D0         26
                   D1         27
A2    B0     C1    D0         34
                   D1         35
      B1     C1    D0         42
                   D1         43
A3    B0     C1    D0         50
                   D1         51
      B1     C1    D0         58
                   D1         59

这里idx[:, :, 'C1', :]是一种更容易编写[slice(None), slice(None),'C1', slice(None)]的方法。您也可以使用较短的np.s_,而不是pd.IndexSlice

我不太清楚其他的工作原理。但请参见文档中的注释:http://pandas.pydata.org/pandas-docs/stable/advanced.html#using-slicers(第一个红色警告框),其中说明:

You should specify all axes in the .loc specifier, meaning the indexer for the index and for the columns. Their are some ambiguous cases where the passed indexer could be mis-interpreted as indexing both axes, rather than into say the MuliIndex for the rows.

这不起作用的原因是需要指定索引轴(在http://pandas.pydata.org/pandas-docs/stable/advanced.html中提到)。解决问题的另一种方法是这样做:

df.loc(axis=0)[:, :, 'C1', :]

当索引相似或包含相似值时,Pandas有时会感到困惑。如果要使用名为“C1”的列或其他列,则还需要在此样式的切片/选择下执行此操作。

相关问题 更多 >

    热门问题