我有一个带有多索引列的 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。
如果第二级 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)