从pandas MultiIndex中选择列

时间:2013-08-27 15:56:40

标签: python pandas multi-index hierarchical

我的DataFrame包含MultiIndex列,如下所示:

# sample data
col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'],
                                ['a', 'b', 'c', 'a', 'b', 'c']])
data = pd.DataFrame(np.random.randn(4, 6), columns=col)
data

sample data

从第二级别选择特定列(例如['a', 'c']而不是范围)的正确,简单方法是什么?

目前我这样做:

import itertools
tuples = [i for i in itertools.product(['one', 'two'], ['a', 'c'])]
new_index = pd.MultiIndex.from_tuples(tuples)
print(new_index)
data.reindex_axis(new_index, axis=1)

expected result

然而,它不是一个好的解决方案,因为我必须淘汰itertools,手工构建另一个MultiIndex然后重新索引(我的实际代码甚至更乱,因为列列表不是'这么简单,以获取)。我很确定必须有一些ixxs方式,但我尝试的所有内容都会导致错误。

7 个答案:

答案 0 :(得分:14)

我认为有一种更好的方式(现在),这就是为什么我在阴影中拉出这个问题(这是谷歌的最佳结果):

data.select(lambda x: x[1] in ['a', 'b'], axis=1)

以快速简洁的单行提供您的预期输出:

        one                 two          
          a         b         a         b
0 -0.341326  0.374504  0.534559  0.429019
1  0.272518  0.116542 -0.085850 -0.330562
2  1.982431 -0.420668 -0.444052  1.049747
3  0.162984 -0.898307  1.762208 -0.101360

主要是自我解释,[1]指的是水平。

答案 1 :(得分:11)

您可以使用,locix我将使用loc显示示例:

data.loc[:, [('one', 'a'), ('one', 'c'), ('two', 'a'), ('two', 'c')]]

如果您有MultiIndexed DataFrame,并且只想过滤掉某些列,则必须传递与这些列匹配的元组列表。因此,itertools方法非常好,但您不必创建新的MultiIndex:

data.loc[:, list(itertools.product(['one', 'two'], ['a', 'c']))]

答案 2 :(得分:5)

这不是很好,但也许:

>>> data
        one                           two                    
          a         b         c         a         b         c
0 -0.927134 -1.204302  0.711426  0.854065 -0.608661  1.140052
1 -0.690745  0.517359 -0.631856  0.178464 -0.312543 -0.418541
2  1.086432  0.194193  0.808235 -0.418109  1.055057  1.886883
3 -0.373822 -0.012812  1.329105  1.774723 -2.229428 -0.617690
>>> data.loc[:,data.columns.get_level_values(1).isin({"a", "c"})]
        one                 two          
          a         c         a         c
0 -0.927134  0.711426  0.854065  1.140052
1 -0.690745 -0.631856  0.178464 -0.418541
2  1.086432  0.808235 -0.418109  1.886883
3 -0.373822  1.329105  1.774723 -0.617690

会起作用吗?

答案 3 :(得分:5)

要在列索引器的第二级选择名为lib'a'的所有列,您可以使用切片器:

'c'

Here您可以阅读有关切片器的更多信息。

答案 4 :(得分:3)

v0.23 +答案。
pd.IndexSlice的使用使locixselect更可取。

有关切片和过滤多索引的更多信息,请访问How do I slice or filter MultiIndex DataFrame levels?


DataFrame.locpd.IndexSlice

# Setup
col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'],
                                ['a', 'b', 'c', 'a', 'b', 'c']])
data = pd.DataFrame('x', index=range(4), columns=col)
data

  one       two      
    a  b  c   a  b  c
0   x  x  x   x  x  x
1   x  x  x   x  x  x
2   x  x  x   x  x  x
3   x  x  x   x  x  x

data.loc[:, pd.IndexSlice[:, ['a', 'c']]]

  one    two   
    a  c   a  c
0   x  x   x  x
1   x  x   x  x
2   x  x   x  x
3   x  x   x  x

您也可以在axis上使用loc参数,以明确指出要从哪个轴索引:

data.loc(axis=1)[pd.IndexSlice[:, ['a', 'c']]]

  one    two   
    a  c   a  c
0   x  x   x  x
1   x  x   x  x
2   x  x   x  x
3   x  x   x  x

MultiIndex.get_level_values
调用data.columns.get_level_values来过滤loc是另一种选择:

data.loc[:, data.columns.get_level_values(1).isin(['a', 'c'])]

  one    two   
    a  c   a  c
0   x  x   x  x
1   x  x   x  x
2   x  x   x  x
3   x  x   x  x

这自然可以允许在单个级别上对任何条件表达式进行过滤。这是一个按字典顺序过滤的随机示例:

data.loc[:, data.columns.get_level_values(1) > 'b']

  one two
    c   c
0   x   x
1   x   x
2   x   x
3   x   x

答案 5 :(得分:2)

在我看来,对Marc P.answer using slice的即兴演奏稍微容易一些:

import pandas as pd
col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'], ['a', 'b', 'c', 'a', 'b', 'c']])
data = pd.DataFrame(np.random.randn(4, 6), columns=col)

data.loc[:, pd.IndexSlice[:, ['a', 'c']]]

        one                 two          
          a         c         a         c
0 -1.731008  0.718260 -1.088025 -1.489936
1 -0.681189  1.055909  1.825839  0.149438
2 -1.674623  0.769062  1.857317  0.756074
3  0.408313  1.291998  0.833145 -0.471879

从大熊猫0.21开始,.select is deprecated in favour of .loc

答案 6 :(得分:0)

最直接的方法是使用.loc

data.loc[:, (['one', 'two'], ['a', 'b'])]


   one       two     
     a    c    a    c
0  0.4 -0.6 -0.7  0.9
1  0.1  0.4  0.5 -0.3
2  0.7 -1.6  0.7 -0.8
3 -0.9  2.6  1.9  0.6

请记住,[]()在处理MultiIndex对象时具有特殊含义:

  

(...)元组被解释为一个多层

     

(...)列表用于指定几个键(在相同级别上)

     

(...)列表的元组引用一个级别中的几个值

当我们写(['one', 'two'], ['a', 'b'])时,元组中的第一个列表指定了MultiIndex的第一层中我们想要的所有值。元组中的第二个列表指定了MultiIndex第二级所需的所有值。

来源:MultiIndex / Advanced Indexing