使用MultiIndex df(pandas)进行布尔索引

时间:2016-12-19 16:17:50

标签: python pandas multi-index

我有一个MultiIndex数据框,我试图根据我的列中的值范围和最外层的索引级别来索引。因此,使用下面的示例,例如我正在尝试从v2中选择l2所在的v1 > 12

的值

我可以使用多个索引语句来实现这一点,例如: 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 个答案:

答案 0 :(得分:1)

您可以使用slicers选择,然后使用loc修改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,则为last:

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