选择具有多索引列的行

And*_*son 5 python pandas

我有一个带有多索引列的 df,如下所示:

col = pd.MultiIndex.from_arrays([['one', '', '', 'two', 'two', 'two'],
                                ['a', 'b', 'c', 'd', 'e', 'f']])
data = pd.DataFrame(np.random.randn(4, 6), columns=col)
data
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我希望能够选择 1 级列之一中的值通过某个测试的所有行。如果列上没有多索引,我会说:

data[data['d']<1]
Run Code Online (Sandbox Code Playgroud)

但当然,这在多重索引上失败了。1 级索引是唯一的,所以我不想指定 0 级索引,只指定 1 级。我想返回上面的表但缺少第 1 行,其中 d>1。

jez*_*ael 3

如果第二级 id 中的值是唯一的,则需要将掩码从一列 DataFrame 转换为Series- 可能的解决方案DataFrame.squeeze

np.random.seed(2019)
col = pd.MultiIndex.from_arrays([['one', '', '', 'two', 'two', 'two'],
                                ['a', 'b', 'c', 'd', 'e', 'f']])
data = pd.DataFrame(np.random.randn(4, 6), columns=col)


print (data.xs('d', axis=1, level=1))
        two
0  1.331864
1  0.953490
2 -0.189313
3  0.064969

print (data.xs('d', axis=1, level=1).squeeze())
0    1.331864
1    0.953490
2   -0.189313
3    0.064969
Name: two, dtype: float64

print (data.xs('d', axis=1, level=1).squeeze().lt(1))
0    False
1     True
2     True
3     True
Name: two, dtype: bool

df = data[data.xs('d', axis=1, level=1).squeeze().lt(1)]
Run Code Online (Sandbox Code Playgroud)

替代方案DataFrame.iloc

df = data[data.xs('d', axis=1, level=1).iloc[:, 0].lt(1)]
Run Code Online (Sandbox Code Playgroud)
print (df)
        one                           two                    
          a         b         c         d         e         f
1  0.573761  0.287728 -0.235634  0.953490 -1.689625 -0.344943
2  0.016905 -0.514984  0.244509 -0.189313  2.672172  0.464802
3  0.845930 -0.503542 -0.963336  0.064969 -3.205040  1.054969
Run Code Online (Sandbox Code Playgroud)

如果在选择后使用MultiIndex可以获取多列,如果按c级别选择,则如下所示:

np.random.seed(2019)
col = pd.MultiIndex.from_arrays([['one', '', '', 'two', 'two', 'two'],
                                ['a', 'b', 'c', 'a', 'b', 'c']])
data = pd.DataFrame(np.random.randn(4, 6), columns=col)
Run Code Online (Sandbox Code Playgroud)

所以首先选择 byDataFrame.xs并比较 by DataFrame.ltfor<

print (data.xs('c', axis=1, level=1))
                  two
0  1.481278  0.685609
1 -0.235634 -0.344943
2  0.244509  0.464802
3 -0.963336  1.054969

m = data.xs('c', axis=1, level=1).lt(1)
#alternative
#m = data.xs('c', axis=1, level=1) < 1
print (m)
            two
0  False   True
1   True   True
2   True   True
3   True  False
Run Code Online (Sandbox Code Playgroud)

然后测试True每行是否至少有一个 byDataFrame.any和 filter by boolean indexing

df1 = data[m.any(axis=1)]
print (df1)
        one                           two                    
          a         b         c         a         b         c
0 -0.217679  0.821455  1.481278  1.331864 -0.361865  0.685609
1  0.573761  0.287728 -0.235634  0.953490 -1.689625 -0.344943
2  0.016905 -0.514984  0.244509 -0.189313  2.672172  0.464802
3  0.845930 -0.503542 -0.963336  0.064969 -3.205040  1.054969
Run Code Online (Sandbox Code Playgroud)

或者通过过滤来测试True每行是否全部 s DataFrame.any

df1 = data[m.all(axis=1)]
print (df1)
        one                           two                    
          a         b         c         a         b         c
1  0.573761  0.287728 -0.235634  0.953490 -1.689625 -0.344943
2  0.016905 -0.514984  0.244509 -0.189313  2.672172  0.464802
Run Code Online (Sandbox Code Playgroud)