我通过两列的值过滤数据帧中的行。
出于某种原因,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才能删除它们。我认为结果完全相反。有人能解释一下这种行为吗?
我使用的是熊猫0.13.1。
根据摩根定律,(i)一个联合的否定是两个否定的交集,(ii)一个交集的否定是两个否定的交集的并,即,
A AND B <=> not A OR not B
A OR B <=> not A AND not B
如果目标是
删除至少有一个值等于-1的每一行
您可以使用AND操作符来标识要保留的行,也可以使用or操作符来标识要删除的行。
# 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运算符来标识要保留的行,要么使用AND运算符来标识要删除的行。
根据摩根定律,(i)一个联合的否定是两个否定的交集,(ii)一个交集的否定是两个否定的交集的并,即,
A AND B <=> not A OR not B
A OR B <=> not A AND not B
如果目标是
删除至少有一个值等于-1的每一行
您可以使用AND操作符来标识要保留的行,也可以使用or操作符来标识要删除的行。
# 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运算符来标识要保留的行,要么使用AND运算符来标识要删除的行。
如您所见,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的习惯。