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

问题描述 投票:0回答:5

我正在按两列中的值过滤数据框中的行。

出于某种原因,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
运算符会删除至少有一个值等于
-1
的每一行。另一方面,
OR
运算符要求两个值都等于
-1
才能删除它们。我期望得到完全相反的结果。谁能解释一下这种行为吗?

我使用的是pandas 0.13.1。

python pandas dataframe indexing boolean-logic
5个回答
378
投票

如您所见,AND 运算符会删除其中至少有一个的每一行 值等于-1。另一方面,OR 运算符需要 值等于 -1 即可删除它们。

没错。请记住,您所写的条件是您想要“保留”的内容,而不是您想要删除的内容。对于df1


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

您的意思是“保留 
df.a

不是 -1 且

df.b
不是 -1 的行”,这与删除其中至少有一个值为 -1 的每一行相同。

对于

df2


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

您的意思是“保留 
df.a

df.b
不为 -1 的行”,这与删除两个值为 -1 的行相同。

PS:像

df['a'][1] = -1

这样的链式访问会给你带来麻烦。最好养成使用

.loc
.iloc
的习惯。
    


76
投票
query()

,例如: df_filtered = df.query('a == 4 & b != 2')



22
投票
数理逻辑理论

“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) 相反(补)是 -1)”. 所以如果你想要完全相反的结果,df1和df2应该如下:

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



1
投票

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



1
投票
德摩根定律

,(i)并集的否定是否定的交集,并且(ii)交集的否定是否定的并集,即, A AND B <=> not A OR not B A OR B <=> not A AND not B

如果目标是

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

您可以使用
AND

运算符来标识要

keep
的行,或使用 OR 运算符来标识要
drop
的行。 # 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 的每一行

你的做法恰恰相反;使用
OR

运算符来标识要

keep
的行,或使用 AND 运算符来标识要
drop
的行。

© www.soinside.com 2019 - 2024. All rights reserved.