33

我怀疑这是微不足道的,但我还没有发现可以让我根据分层键的值从 Pandas 数据框中选择行的咒语。因此,例如,假设我们有以下数据框:

import pandas
df = pandas.DataFrame({'group1': ['a','a','a','b','b','b'],
                       'group2': ['c','c','d','d','d','e'],
                       'value1': [1.1,2,3,4,5,6],
                       'value2': [7.1,8,9,10,11,12]
})
df = df.set_index(['group1', 'group2'])

df 看起来和我们预期的一样:

在此处输入图像描述

如果 df 没有在 group1 上被索引,我可以执行以下操作:

df['group1' == 'a']

但是在这个带有索引的数据帧上失败了。所以也许我应该把它想象成一个带有层次索引的熊猫系列:

df['a','c']

没有。那也失败了。

那么如何选择所有行:

  1. 组 1 == 'a'
  2. group1 == 'a' & group2 == 'c'
  3. 组 2 == 'c'
  4. ['a','b','c'] 中的组 1
4

3 回答 3

49

尝试使用xs非常精确:

In [5]: df.xs('a', level=0)
Out[5]: 
        value1  value2
group2                
c          1.1     7.1
c          2.0     8.0
d          3.0     9.0

In [6]: df.xs('c', level='group2')
Out[6]: 
        value1  value2
group1                
a          1.1     7.1
a          2.0     8.0
于 2012-08-13T21:37:08.807 回答
9

如下语法将起作用:

df.ix['a']
df.ix['a'].ix['c']

因为group1group2是索引。请原谅我之前的尝试!

要仅获得第二个索引,我认为您必须交换索引:

df.swaplevel(0,1).ix['c']

但我敢肯定,如果我错了,韦斯会纠正我的。

于 2012-08-13T20:26:38.163 回答
1

在 Python 0.19.0 中,有一种新的建议方法,此处解释1。我相信他们给出的最清晰的例子如下,他们从一个四级索引中分割出来。这就是数据框的制作方式:

In [46]: def mklbl(prefix,n):
   ....:     return ["%s%s" % (prefix,i)  for i in range(n)]
   ....: 

In [47]: miindex = pd.MultiIndex.from_product([mklbl('A',4),
   ....:                                       mklbl('B',2),
   ....:                                       mklbl('C',4),
   ....:                                       mklbl('D',2)])
   ....: 

In [48]: micolumns = pd.MultiIndex.from_tuples([('a','foo'),('a','bar'),
   ....:                                        ('b','foo'),('b','bah')],
   ....:                                       names=['lvl0', 'lvl1'])
   ....: 

In [49]: dfmi = pd.DataFrame(np.arange(len(miindex)*len(micolumns)).reshape((len(miindex),len(micolumns))),
   ....:                     index=miindex,
   ....:                     columns=micolumns).sort_index().sort_index(axis=1)
   ....: 

In [50]: dfmi
Out[50]: 
lvl0           a         b     
lvl1         bar  foo  bah  foo
A0 B0 C0 D0    1    0    3    2
         D1    5    4    7    6
      C1 D0    9    8   11   10
         D1   13   12   15   14
      C2 D0   17   16   19   18
         D1   21   20   23   22
      C3 D0   25   24   27   26
...          ...  ...  ...  ...
A3 B1 C0 D1  229  228  231  230
      C1 D0  233  232  235  234
         D1  237  236  239  238
      C2 D0  241  240  243  242
         D1  245  244  247  246
      C3 D0  249  248  251  250
         D1  253  252  255  254

这就是他们选择不同行的方式:

In [51]: dfmi.loc[(slice('A1','A3'),slice(None), ['C1','C3']),:]
Out[51]: 
lvl0           a         b     
lvl1         bar  foo  bah  foo
A1 B0 C1 D0   73   72   75   74
         D1   77   76   79   78
      C3 D0   89   88   91   90
         D1   93   92   95   94
   B1 C1 D0  105  104  107  106
         D1  109  108  111  110
      C3 D0  121  120  123  122
...          ...  ...  ...  ...
A3 B0 C1 D1  205  204  207  206
      C3 D0  217  216  219  218
         D1  221  220  223  222
   B1 C1 D0  233  232  235  234
         D1  237  236  239  238
      C3 D0  249  248  251  250
         D1  253  252  255  254

所以很简单,在 中df.loc[(indices),:],您指定要选择的每个级别的索引,从最高级别到最低级别。如果您不想选择最低级别的索引,则可以省略指定它们。如果您不想在其他指定级别之间进行切片,请添加slice(None). 示例中显示了这两种情况,其中省略了 D 级,在 A 和 C 之间指定了 B 级。

于 2016-10-20T09:02:01.477 回答