太长,读不下去了
熊猫中的逻辑运算符是
&
,
|
和
~
,和括号
(...)
这很重要!
蟒蛇的
and
,
or
和
not
逻辑运算符设计用于处理标量。所以Pandas必须做得更好,重写位运算符以实现
矢量化
此功能的(元素)版本。
下面是python中的(
exp1
和
exp2
是计算为布尔结果的表达式)。。。
exp1 and exp2 # Logical AND
exp1 or exp2 # Logical OR
not exp1 # Logical NOT
...将转化为。。。
exp1 & exp2 # Element-wise logical AND
exp1 | exp2 # Element-wise logical OR
~exp1 # Element-wise logical NOT
为了熊猫。
如果在执行逻辑运算的过程中
ValueError
,则需要使用括号进行分组:
(exp1) op (exp2)
例如
(df['col1'] == x) & (df['col2'] == y)
等等
Boolean Indexing
:常见的操作是通过逻辑条件计算布尔掩码以过滤数据。熊猫提供
三
操作员:
&
对于逻辑和逻辑,
|
用于逻辑OR,以及
~
当然不是。
考虑以下设置:
np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))
df
A B C
0 5 0 3
1 3 7 9
2 3 5 2
3 4 7 6
4 8 8 1
逻辑与
对于
df
上面,假设您希望返回A<5和B>5.这是通过分别计算每个条件的掩码,并对它们进行求和来实现的。
按位重载
&
操作人员
在继续之前,请注意这些文件的特别摘录,其中
另一种常见的操作是使用布尔向量来过滤
数据运营商包括:
|
对于
或
,
&
对于
和
和
~
对于
不
.
这些
,因为默认情况下Python将
计算表达式,例如
df.A > 2 & df.B < 3
像
df.A > (2 &
df.B) < 3
,而所需的评估顺序为
(df.A > 2) & (df.B <
3)
.
因此,考虑到这一点,元素逻辑AND可以通过位运算符实现
&
:
df['A'] < 5
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'] > 5
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
(df['A'] < 5) & (df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
接下来的过滤步骤很简单,
df[(df['A'] < 5) & (df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
括号用于覆盖按位运算符的默认优先顺序,按位运算符的优先级高于条件运算符
<
和
>
.参见
Operator Precedence
在python文档中。
如果不使用括号,则表达式的计算结果不正确。例如,如果您不小心尝试了以下操作:
df['A'] < 5 & df['B'] > 5
它被解析为
df['A'] < (5 & df['B']) > 5
这就变成了,
df['A'] < something_you_dont_want > 5
这就变成了(参见上的python文档)
chained operator comparison
),
(df['A'] < something_you_dont_want) and (something_you_dont_want > 5)
这就变成了,
# Both operands are Series...
something_else_you_dont_want1 and something_else_you_dont_want2
哪个扔
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
所以,不要犯那个错误!
1.
避免括号分组
解决方法其实很简单。对于数据帧,大多数操作符都有相应的绑定方法。如果单个掩码是使用函数而不是条件运算符构建的,则不再需要按参数分组来指定求值顺序:
df['A'].lt(5)
0 True
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'].gt(5)
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
df['A'].lt(5) & df['B'].gt(5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
请参阅
Flexible Comparisons.
.总结一下,我们有
ââââââ¤âââââââââââââ¤âââââââââââââ
â â Operator â Function â
ââââââªâââââââââââââªâââââââââââââ¡
â 0 â > â gt â
ââââââ¼âââââââââââââ¼âââââââââââââ¤
â 1 â >= â ge â
ââââââ¼âââââââââââââ¼âââââââââââââ¤
â 2 â < â lt â
ââââââ¼âââââââââââââ¼âââââââââââââ¤
â 3 â <= â le â
ââââââ¼âââââââââââââ¼âââââââââââââ¤
â 4 â == â eq â
ââââââ¼âââââââââââââ¼âââââââââââââ¤
â 5 â != â ne â
ââââââ§âââââââââââââ§âââââââââââââ
避免使用括号的另一个选项是使用
DataFrame.query
(或
eval
):
df.query('A < 5 and B > 5')
A B C
1 3 7 9
3 4 7 6
我有
广泛地
记录在案
query
和
评估
在里面
Dynamic Expression Evaluation in pandas using pd.eval()
.
operator.and_
允许您以功能性方式执行此操作。内部通话
Series.__and__
它对应于按位运算符。
import operator
operator.and_(df['A'] < 5, df['B'] > 5)
# Same as,
# (df['A'] < 5).__and__(df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
df[operator.and_(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
你通常不需要这个,但知道它很有用。
概括起来:
np.logical_and
(及
logical_and.reduce
)
另一种选择是使用
NP逻辑_和
,也不需要括号:
np.logical_and(df['A'] < 5, df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
Name: A, dtype: bool
df[np.logical_and(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
NP逻辑_和
是一个
ufunc (Universal Functions)
,而且大多数UFUNC都有
reduce
方法这意味着更容易概括
logical_and
如果你有多个口罩和。比如说,戴口罩和口罩
m1
和
m2
和
m3
具有
&
,你必须这么做
m1 & m2 & m3
然而,一个更简单的选择是
np.logical_and.reduce([m1, m2, m3])
这是非常强大的,因为它可以让你在上面构建更复杂的逻辑(例如,在列表中动态生成掩码并添加所有掩码):
import operator
cols = ['A', 'B']
ops = [np.less, np.greater]
values = [5, 5]
m = np.logical_and.reduce([op(df[c], v) for op, c, v in zip(ops, cols, values)])
m
# array([False, True, False, True, False])
df[m]
A B C
1 3 7 9
3 4 7 6
1-我知道我在反复强调这一点,但请容忍我。这是一个
非常
,
非常
初学者常见的错误,必须解释得非常透彻。
逻辑或
对于
df
上面,假设您希望返回A==3或B==7的所有行。
按位重载
|
df['A'] == 3
0 False
1 True
2 True
3 False
4 False
Name: A, dtype: bool
df['B'] == 7
0 False
1 True
2 False
3 True
4 False
Name: B, dtype: bool
(df['A'] == 3) | (df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[(df['A'] == 3) | (df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
如果还没有,请阅读
逻辑与
或者,也可以使用
df[df['A'].eq(3) | df['B'].eq(7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
operator.or_
电话
Series.__or__
在引擎盖下面。
operator.or_(df['A'] == 3, df['B'] == 7)
# Same as,
# (df['A'] == 3).__or__(df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[operator.or_(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
np.logical_or
对于两种情况,使用
logical_or
:
np.logical_or(df['A'] == 3, df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df[np.logical_or(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
对于多个遮罩,请使用
logical_or.reduce
:
np.logical_or.reduce([df['A'] == 3, df['B'] == 7])
# array([False, True, True, True, False])
df[np.logical_or.reduce([df['A'] == 3, df['B'] == 7])]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
不符合逻辑
戴上口罩,比如
mask = pd.Series([True, True, False])
如果需要反转每个布尔值(以便最终结果为
[False, False, True]
),则可以使用以下任何方法。
按位
~
~mask
0 False
1 False
2 True
dtype: bool
同样,表达式需要加括号。
~(df['A'] == 3)
0 True
1 False
2 False
3 True
4 True
Name: A, dtype: bool
这在内部称为
mask.__invert__()
0 False
1 False
2 True
dtype: bool
但不要直接使用它。
operator.inv
内部通话
__invert__
在这个系列中。
operator.inv(mask)
0 False
1 False
2 True
dtype: bool
np.logical_not
这是numpy的变种。
np.logical_not(mask)
0 False
1 False
2 True
dtype: bool
笔记
NP逻辑_和
可以替代
np.bitwise_and
,
逻辑的
具有
bitwise_or
和
logical_not
具有
invert
.