基于索引的条件切片多级索引DataFrame

6

我有一个类似这样的数据框:

import pandas as pd
import numpy as np

arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']), np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'])]
df = pd.DataFrame([[24, 13,  8,  9],
   [11, 30,  7, 23],
   [21, 31, 12, 30],
   [ 2,  5, 19, 24],
   [15, 18,  3, 16],
   [ 2, 24, 28, 11],
   [23,  9,  6, 12],
   [29, 28, 11, 21]], index=arrays, columns=list('abcd'))


df
          a   b   c   d
bar one  24  13   8   9
    two  11  30   7  23
baz one  21  31  12  30
    two   2   5  19  24
foo one  15  18   3  16
    two   2  24  28  11
qux one  23   9   6  12
    two  29  28  11  21

我希望切片数据框,使得结果包含所有第一级索引为foo的行和所有第一级索引为bar且第二级索引为two的行。即,结果数据框应该如下所示:
          a   b   c   d
bar two  11  30   7  23
foo one  15  18   3  16
    two   2  24  28  11

获得此结果的一种方法是

pd.concat([df.loc[[('bar', 'two')],:], df.loc[('foo', slice(None)),:]])

但是这种方式感觉非常繁琐,一定有更符合Python风格的方法。

为什么不直接使用reset_index呢 :-) - BENY
@Wen 我刚想到可以使用.loc / .xs方法来获取结果,但我无法弄清楚。 - crs
2个回答

7
您可以使用默认切片。
l0 = df.index.get_level_values(0)
l1 = df.index.get_level_values(1)
cond = (l0 == "foo") | ((l0=="bar") & (l1=="two"))
df[cond]

输出

        a   b   c   d
bar two 11  30  7   23
foo one 15  18  3   16
    two 2   24  28  11

6

查询来拯救:

df.query('ilevel_0 == "foo" or (ilevel_0 == "bar" and ilevel_1 == "two")')

          a   b   c   d
bar two  11  30   7  23
foo one  15  18   3  16
    two   2  24  28  11
< p > < code > xs ,< code > loc 等都失败了,因为您对跨级别进行的切片不一致。

1
使用pandas进行年份操作,从未听说过.query。是否有一种方法可以命名索引,以便可以使用这些名称而不是“ilevel_0”、“ilevel_1”等? - crs
@crs 当然可以,使用 df = df.rename_axis(['name1', 'name2']),然后你可以用你自己的名称替换 ilevel_*。 - cs95

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接