2016-12-19 31 views
2

我有一个MultiIndex数据框,我试图索引基于我的列中的值范围和最外层的索引级别。因此,使用下面的例子,例如我试图从v2是指数l2其中v1 > 12MultiIndex df(熊猫)布尔索引

我可以实现选择值这个使用多个索引的语句,如: df[df.v1>12].loc['l2', 'v2'],但这似乎不太理想。有没有办法将这个简化成一个单一的陈述?

我一直在试图弄清楚如何使用pd.IndexSlice,但似乎无法包装我的头在文档的MultiIndex部分中的示例正在做什么。

df = pd.concat([pd.DataFrame({'v1': range(10, 15), 'v2':range(5, 0, -1)}) 
       for i in range(2)], keys=['l1', 'l2']) 

     v1 v2 
l1 0 10 5 
    1 11 4 
    2 12 3 
    3 13 2 
    4 14 1 
l2 0 10 5 
    1 11 4 
    2 12 3 
    3 13 2 
    4 14 1 

回答

1

可以用于选择,然后使用与slicersloc改性boolean indexing用于选择列v2

idx = pd.IndexSlice 
df1 = df.loc[idx['l2', :], :] 
print (df1) 
     v1 v2 
l2 0 10 5 
    1 11 4 
    2 12 3 
    3 13 2 
    4 14 1 

print (df1.loc[df1.v1 > 12, 'v2']) 
l2 3 2 
    4 1 
Name: v2, dtype: int32 

xs另一种解决方案:

df1 = df.xs('l2') 
print (df1) 
    v1 v2 
0 10 5 
1 11 4 
2 12 3 
3 13 2 
4 14 1 

print (df1.loc[df1.v1 > 12, 'v2']) 
3 2 
4 1 
Name: v2, dtype: int32 

df1 = df.xs('l2', drop_level=False) 
print (df1) 
     v1 v2 
l2 0 10 5 
    1 11 4 
    2 12 3 
    3 13 2 
    4 14 1 

print (df1.loc[df1.v1 > 12, 'v2']) 
l2 3 2 
    4 1 
Name: v2, dtype: int32 

解由get_level_values选择指数的第一电平,最后如果需要除去第一级使用droplevelreset_index

df1 = df.loc[(df.v1 > 12) & (df.index.get_level_values(0) == 'l2'), 'v2'] 
df1.index = df1.index.droplevel(0) 
#df1 = df1.reset_index(level=0, drop=True) 
print (df1) 
3 2 
4 1 
Name: v2, dtype: int32 

实施例与IndexSlice

在第一水平和第二选择的所有值从13(谢谢piRSquared):

idx = pd.IndexSlice 
print (df.loc[idx[:, 1:3], :]) 
     v1 v2 
l1 1 11 4 
    2 12 3 
    3 13 2 
l2 1 11 4 
    2 12 3 
    3 13 2 
+0

@piRSquared - 谢谢。 – jezrael

+0

感谢您的详细回复。我想我真正的问题是,是否有一种方法可以实现这一点,而不必将索引的多个过程链接到数据框的不同部分。除了使用'get_level_values',我认为它有点笨重,答案似乎是,没有比我已经做的更详细的方式。 – user3014097

+0

是的,你是对的。是不可能的使用布尔索引与索引一起选择。如果选中[cookbook](http://pandas.pydata.org/pandas-docs/stable/cookbook.html#dataframes),则会出现类似的示例[29] - 按掩码选择带索引掩码的列。美好的一天,祝你好运。 – jezrael