"太多的索引器"使用DataFrame.loc

时间:2015-06-11 12:38:51

标签: python pandas

我已经阅读了the docs about slicers一百万次,但我从来没有理解它,所以我仍然在试图弄清楚如何使用loc切片{ {1}} DataFrame

我将从this SO answer开始使用MultiIndex

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 A0值,我可以这样做:

C1

哪个也适用于三个级别,甚至是元组:

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')行为似乎不一致。

2 个答案:

答案 0 :(得分:15)

这不起作用的原因与指定索引轴的需要有关(在http://pandas.pydata.org/pandas-docs/stable/advanced.html中提到)。解决问题的另一种方法是简单地执行此操作:

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

当索引相似或包含类似值时,Pandas有时会感到困惑。如果你有一个名为&#39; C1&#39;或者你需要在这种切片/选择方式下做这件事。

答案 1 :(得分:13)

为了安全(在某种意义上:这将适用于所有情况),您需要为行索引和列编制索引,您可以使用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)]。除了pd.IndexSlice之外,您还可以使用更短的np.s_

其他人工作的原因,我不完全确定。但请参阅此处文档中的说明:http://pandas.pydata.org/pandas-docs/stable/advanced.html#using-slicers(第一个红色警告框),其中声明:

  

您应该在.loc说明符中指定所有轴,这意味着索引和列的索引器。它们是一些模糊的情况,传递的索引器可能被误解为索引两个轴,而不是行的MuliIndex。