在不删除行的情况下过滤Pandas DataFrame

5
我正在尝试在Pandas DataFrame上使用“where”操作,在其中用“NaN”替换所有不符合我的条件的单元格。但是,我希望以一种始终保留原始DataFrame形状且不从结果DataFrame中删除任何行的方式来执行此操作。
给定以下DataFrame:
      A    B    C    D
1/1   0    1    0    1
1/2   2    1    1    1
1/3   3    0    1    0 
1/4   1    0    1    2
1/5   1    0    1    1
1/6   2    0    2    1
1/7   3    5    2    3

我希望能够搜索数据框中符合特定条件的所有单元格,当列 D 同时满足特定条件时。在这种情况下,我的条件是:

查找所有大于前一个值的单元格,当列 D 也 > 1 时

我通过使用以下语法来实现:

matches = df[df > df.shift(1))]
matches = matches[df.D > 1]

我必须将这个查询拆成两个语句,因为 df.D 是一个 Series,与整个 DataFrame 的形状不匹配。根据我之前提出的这个问题,支持广播运算符 & 将在0.14之后才可用。
我的问题是,在运行第二个语句之后,似乎结果数据框的形状发生了变化,并且已经删除了几行,但列数保持不变。而第一个语句则保留原始的行数。
为什么第二个语句会删除行,而第一个不会?如何实现相同的结果,但保留完整的行数?
编辑:
Pandas 文档指出,为了保证形状不变,应该使用 where 方法进行布尔索引。然而,似乎无法对我的第二个语句执行此操作。
matches.where(df.D > 1)

给我以下错误:
ValueError:数组条件必须与自身形状相同
2个回答

6
这比@DSM的答案更直观一些(但是目前pandas在布尔操作上缺少这种自动广播类型)。
In [58]: df.where((df>df.shift(1)).values & DataFrame(df.D==1).values)
Out[58]: 
      A   B   C   D
1/1 NaN NaN NaN NaN
1/2   2 NaN   1 NaN
1/3 NaN NaN NaN NaN
1/4 NaN NaN NaN NaN
1/5 NaN NaN NaN NaN
1/6   2 NaN   2 NaN
1/7 NaN NaN NaN NaN

点击这里查看需要在0.14版本中解决的问题。


谢谢Jeff,那个完美地解决了问题。你知道切换到numpy数组是否会有任何性能问题吗?我会错过pandas数据框架提供的任何性能优化吗?在我的实际、更大的用例中,它表现得足够好,但只是好奇。 - mclark1129

3

如果我理解你的意思,你可以通过手动降到numpy级别来进行广播:

>>> (df > df.shift(1)).values & (df.D == 1)[:,None]
array([[False, False, False, False],
       [ True, False,  True, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [ True, False,  True, False],
       [False, False, False, False]], dtype=bool)

之后您可以使用 where

>>> df.where((df > df.shift(1)).values & (df.D == 1)[:,None], np.nan)
      A   B   C   D
1/1 NaN NaN NaN NaN
1/2   2 NaN   1 NaN
1/3 NaN NaN NaN NaN
1/4 NaN NaN NaN NaN
1/5 NaN NaN NaN NaN
1/6   2 NaN   2 NaN
1/7 NaN NaN NaN NaN

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