我的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
从第二级别选择特定列(例如['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)
然而,它不是一个好的解决方案,因为我必须淘汰itertools
,手工构建另一个MultiIndex然后重新索引(我的实际代码甚至更乱,因为列列表不是'这么简单,以获取)。我很确定必须有一些ix
或xs
方式,但我尝试的所有内容都会导致错误。
答案 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)
您可以使用,loc
或ix
我将使用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)
答案 4 :(得分:3)
v0.23 +答案。
pd.IndexSlice
的使用使loc
比ix
和select
更可取。
有关切片和过滤多索引的更多信息,请访问How do I slice or filter MultiIndex DataFrame levels?。
# 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
第二级所需的所有值。