pandas:索引数据框时出现多个条件 - 意外行为

pandas: multiple conditions while indexing data frame - unexpected behavior

提问人:Wojciech Walczak 提问时间:3/23/2014 最后编辑:cottontailWojciech Walczak 更新时间:1/5/2023 访问量:638221

问:

我正在按两列中的值筛选数据帧中的行。

出于某种原因,OR 运算符的行为与我期望的 AND 运算符的行为类似,反之亦然。

我的测试代码:

df = pd.DataFrame({'a': range(5), 'b': range(5) })

# let's insert some -1 values
df['a'][1] = -1
df['b'][1] = -1
df['a'][3] = -1
df['b'][4] = -1

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a != -1) | (df.b != -1)]

print(pd.concat([df, df1, df2], axis=1,
                keys = [ 'original df', 'using AND (&)', 'using OR (|)',]))

结果:

      original df      using AND (&)      using OR (|)    
             a  b              a   b             a   b
0            0  0              0   0             0   0
1           -1 -1            NaN NaN           NaN NaN
2            2  2              2   2             2   2
3           -1  3            NaN NaN            -1   3
4            4 -1            NaN NaN             4  -1

[5 rows x 6 columns]

如您所见,运算符删除了其中至少有一个值等于 的每行。另一方面,运算符要求两个值都等于 才能删除它们。我期望完全相反的结果。谁能解释这种行为?AND-1OR-1

我正在使用 pandas 0.13.1。

Python Pandas DataFrame 索引布尔 逻辑

评论


答:

376赞 DSM 3/23/2014 #1

正如你所看到的,AND 运算符删除了至少 value 等于 -1。另一方面,OR 运算符需要两者 值等于 -1 以删除它们。

没错。请记住,您是根据要保留的内容来编写条件,而不是根据要删除的内容来编写条件。为:df1

df1 = df[(df.a != -1) & (df.b != -1)]

您说“保留不是 -1 且不是 -1 的行”,这与删除至少有一个值为 -1 的每一行相同。df.adf.b

为:df2

df2 = df[(df.a != -1) | (df.b != -1)]

您说的是“保留其中 or 不是 -1 的行”,这与删除两个值均为 -1 的行相同。df.adf.b

PS:链式访问可能会给您带来麻烦。最好养成使用 和 的习惯。df['a'][1] = -1.loc.iloc

75赞 Pedro Lobito 11/28/2016 #2

迟到的答案,但你也可以使用 query(),即:

df_filtered = df.query('a == 4 & b != 2')
22赞 Jake 10/13/2018 #3

这里有一点数理逻辑理论

“NOT a AND NOT b”与“NOT (a OR b)”相同,因此:

“a NOT -1 AND b NOT -1” 等价于 “NOT (a is -1 OR b is -1)”,与 “(a is -1 OR b is -1) 相反(补码)。

因此,如果您想要完全相反的结果,df1 和 df2 应如下所示:

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a == -1) | (df.b == -1)]
1赞 Mohammad Rahimi 8/13/2022 #4

您可以尝试以下操作:

df1 = df[(df['a'] != -1) & (df['b'] != -1)]       

评论

0赞 rachwa 8/14/2022
这与公认的答案基本相同。
0赞 NineTails 8/17/2022
2 年后,您重新发布了已接受的解决方案的一行。请不要那样做 - 它不会为讨论增加任何东西。
1赞 cottontail 9/14/2022 #5

根据德摩根定律,(i)并集的否定是否定是否定的交集,(ii)交集的否定是否定的并集,即

A AND B <=> not A OR not B
A OR B  <=> not A AND not B

如果目标是

删除至少一个值等于 -1 的每一行

您可以使用 Operator 来标识要保留的行,也可以使用 Operator 来标识要删除的行。ANDOR

# select rows where both a and b values are not equal to -1
df2_0 = df[df['a'].ne(-1) & df['b'].ne(-1)]

# index of rows where at least one of a or b equals -1
idx = df.index[df.eval('a == -1 or b == -1')]
# drop `idx` rows
df2_1 = df.drop(idx)

df2_0.equals(df2_1) # True

另一方面,如果目标是

删除两个值都等于 -1 的每一行

你做的恰恰相反;使用 Operator 标识要保留的行,或使用 Operator 标识要删除的行。ORAND