如何根据一列中的条件从多索引数据框中选择行

时间:2021-07-10 01:50:21

标签: python pandas dataframe

我有一个如下所示的多索引数据框:

df = {'C': {('S', 0): 'A',
  ('S', 2): 'A',
  ('T', 0): 'A',
  ('T', 1): 'A',
  ('T', 3): 'A',
  ('U', 1): 'A',
  ('U', 2): 'A',
  ('U', 0): 'A',
  ('V', 0): 'A',
  ('W', 2): 'A',
  ('W', 0): 'A',
  ('X', 0): 'A',
  ('Y', 3): 'A',
  ('Z', 0): 'A',
  ('Z', 1): 'A'},
 'D': {('S', 0): '15',
  ('S', 2): '22',
  ('T', 0): '20',
  ('T', 1): '20',
  ('T', 3): '20',
  ('U', 1): '18',
  ('U', 2): '14',
  ('U', 0): '14',
  ('V', 0): '14',
  ('W', 2): '22',
  ('W', 0): '25',
  ('X', 0): '15',
  ('Y', 3): '17',
  ('Z', 0): '04',
  ('Z', 1): '16'},
 'E': {('S', 0): 1.0,
  ('S', 2): 1.0,
  ('T', 0): 2.0,
  ('T', 1): 2.0,
  ('T', 0): 2.0,
  ('U', 1): 2.0,
  ('U', 2): 2.0,
  ('U', 0): 2.0,
  ('V', 0): 1.0,
  ('W', 2): 1.0,
  ('W', 0): 1.0,
  ('X', 0): 1.0,
  ('Y', 3): 2.0,
  ('Z', 0): 3.0,
  ('Z', 1): 3.0}}

如果在其级别 1 中有一个值 >=2

,我想保留级别 0 行

输出将如下所示:

outp = {'C': {('S', 0): 'A',
  ('S', 2): 'A',
  ('T', 0): 'A',
  ('T', 1): 'A',
  ('T', 3): 'A',
  ('U', 1): 'A',
  ('U', 2): 'A',
  ('U', 0): 'A',
  ('W', 2): 'A',
  ('W', 0): 'A',
  ('Y', 3): 'A'},
 'D': {('S', 0): '15',
  ('S', 2): '22',
  ('T', 0): '20',
  ('T', 1): '20',
  ('T', 3): '20',
  ('U', 1): '18',
  ('U', 2): '14',
  ('U', 0): '14',
  ('W', 2): '22',
  ('W', 0): '25',
  ('Y', 3): '17'},
 'E': {('S', 0): 1.0,
  ('S', 2): 1.0,
  ('T', 0): 2.0,
  ('T', 1): 2.0,
  ('T', 0): 2.0,
  ('U', 1): 2.0,
  ('U', 2): 2.0,
  ('U', 0): 2.0,
  ('W', 2): 1.0,
  ('W', 0): 1.0,
  ('Y', 3): 2.0}}

我所做的是当级别 1 >= 2 时我从级别 0 获得值,但是因为这样做时我从级别 1 中删除了应该保留的值 0 和 1,所以我不得不使用获得的值创建另一个数据框然后使用“内部”合并。我得到了想要的输出,但可以肯定的是我花了很长时间而且可能很愚蠢。

我怎样才能以更好的方式做到这一点?

谢谢。

3 个答案:

答案 0 :(得分:3)

让我们尝试在 level=0 上使用 groupby filter 并过滤以在索引级别 1 (any) 中的 get_level_values 值大于或等于 2 时保留级别 0 值:

outp = (
    df.groupby(level=0)
        .filter(lambda s: (s.index.get_level_values(1) >= 2).any())
)

outp

     C   D    E
S 0  A  15  1.0
  2  A  22  1.0
T 0  A  20  2.0
  1  A  20  2.0
  3  A  20  NaN
U 1  A  18  2.0
  2  A  14  2.0
  0  A  14  2.0
W 2  A  22  1.0
  0  A  25  1.0
Y 3  A  17  2.0

答案 1 :(得分:3)

获取级别 0 中的索引,其中级别 1 >= 2,并索引主 df :

df.loc[df.query("ilevel_1 > =2").index.get_level_values(0)]

     C   D    E
S 0  A  15  1.0
  2  A  22  1.0
T 0  A  20  2.0
  1  A  20  2.0
  3  A  20  NaN
U 1  A  18  2.0
  2  A  14  2.0
  0  A  14  2.0
W 2  A  22  1.0
  0  A  25  1.0
Y 3  A  17  2.0

答案 2 :(得分:1)

这是一种不同的方式:

(df.loc[df.reset_index(level=1)
        .groupby(level=0)['level_1']
        .transform(lambda x: x.ge(2).any()).to_numpy()])