从具有复合(层次)索引的Pandas数据框中选择行

2024-05-13 23:29:29 发布

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

我怀疑这是微不足道的,但是我还没有发现一个咒语,它可以让我从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看起来和我们预期的一样:

enter image description here

如果df未在group1上编制索引,我可以执行以下操作:

df['group1' == 'a']

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

df['a','c']

没有。那也失败了。

那么,如何选择所有行,其中:

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

Tags: 数据importdataframepandasdfindex咒语set
3条回答

尝试使用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

语法如下:

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

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

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

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

但我相信如果我错了韦斯会纠正我的。

在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被省略,级别B在A和C之间指定

相关问题 更多 >