Python 如何在多索引中选择级别组合?
我有以下数据帧:Python 如何在多索引中选择级别组合?,python,pandas,Python,Pandas,我有以下数据帧: import numpy as np import pandas as pd index = pd.MultiIndex.from_product([[1, 2], ['a', 'b', 'c'], ['a', 'b', 'c']], names=['one', 'two', 'three']) df = pd.DataFrame(np.random.rand(18, 3), index=index)
import numpy as np
import pandas as pd
index = pd.MultiIndex.from_product([[1, 2], ['a', 'b', 'c'], ['a', 'b', 'c']],
names=['one', 'two', 'three'])
df = pd.DataFrame(np.random.rand(18, 3), index=index)
0 1 2
one two three
1 a b 0.002568 0.390393 0.040717
c 0.943853 0.105594 0.738587
b b 0.049197 0.500431 0.001677
c 0.615704 0.051979 0.191894
2 a b 0.748473 0.479230 0.042476
c 0.691627 0.898222 0.252423
b b 0.270330 0.909611 0.085801
c 0.913392 0.519698 0.451158
我想选择索引级别两个
和三个
组合为(a,b)
或(b,c)
的行。我该怎么做
我尝试了df.loc[(片(无),['a','b',['b','c']),:]
,但这给了我[a,b]
和[b,c]
的所有组合,包括(a,c)
和(b,b)
,这是不需要的
我尝试了df.loc[pd.MultiIndex.from_tuples([(None,'a','b'),(None,'b','c')])
,但在索引的one层返回NaN
df.loc[pd.MultiIndex.from_tuples([(None, 'a', 'b'), (None, 'b', 'c')])]
0 1 2
NaN a b NaN NaN NaN
b c NaN NaN NaN
所以我想我需要一个one
级别的切片,但这给了我一个TypeError
:
pd.MultiIndex.from_tuples([(slice(None), 'a', 'b'), (slice(None), 'b', 'c')])
TypeError: unhashable type: 'slice'
我觉得这里缺少了一些简单的一行:)。使用:
更新:我们也可以动态生成这样的“查询”:
In [185]: l = [('a','b'), ('b','c')]
In [186]: q = ' or '.join(["(two=='{}' and three=='{}')".format(x,y) for x,y in l])
In [187]: q
Out[187]: "(two=='a' and three=='b') or (two=='b' and three=='c')"
In [188]: df.query(q)
Out[188]:
0 1 2
one two three
1 a b 0.211555 0.193317 0.623895
b c 0.685047 0.369135 0.899151
2 a b 0.082099 0.555929 0.524365
b c 0.901859 0.068025 0.742212
这里有一种使用loc
和get\u level\u值的方法
In [3231]: idx = df.index.get_level_values
In [3232]: df.loc[((idx('two') == 'a') & (idx('three') == 'b')) |
((idx('two') == 'b') & (idx('three') == 'c'))]
Out[3232]:
0 1 2
one two three
1 a b 0.442332 0.380669 0.832598
b c 0.458145 0.017310 0.068655
2 a b 0.933427 0.148962 0.569479
b c 0.727993 0.172090 0.384461
通用方式
In [3262]: conds = [('a', 'b'), ('b', 'c')]
In [3263]: mask = np.column_stack(
[(idx('two') == c[0]) & (idx('three') == c[1]) for c in conds]
).any(1)
In [3264]: df.loc[mask]
Out[3264]:
0 1 2
one two three
1 a b 0.442332 0.380669 0.832598
b c 0.458145 0.017310 0.068655
2 a b 0.933427 0.148962 0.569479
b c 0.727993 0.172090 0.384461
我看到了一个好问题。我投赞成票ᴏʟᴅsᴘᴇᴇᴅ, 对于多索引-仅当它们命名为…;-)而且,不应该与列名冲突。一个懒惰的pd.concat([df.loc[(slice(None),+x,:]对于[('A','b'),('b','c')]])
代码段,必须有更好的方法来使用多个切片。谢谢@MaxU!只是对你回答的速度感到困惑:)。因此,对于我的最小示例,查询非常有效。我实际上有很多组合可供选择。动态构造一个长字符串查询感觉有点笨拙-还有“矢量化”方法吗?@MaxU——我知道,所以我说lazy,不知道如何使用切片进行多线程查询
In [3262]: conds = [('a', 'b'), ('b', 'c')]
In [3263]: mask = np.column_stack(
[(idx('two') == c[0]) & (idx('three') == c[1]) for c in conds]
).any(1)
In [3264]: df.loc[mask]
Out[3264]:
0 1 2
one two three
1 a b 0.442332 0.380669 0.832598
b c 0.458145 0.017310 0.068655
2 a b 0.933427 0.148962 0.569479
b c 0.727993 0.172090 0.384461