慕沐林林
Pandas中的逻辑运算符是&, |和~,和括号(...)很重要!Python的and, or和not逻辑运算符设计用于处理标量。因此,Pandas必须做得更好,并重写按位运算符来实现。矢量化(就元素而言)此功能的版本。下面是python中的内容(exp1和exp2是计算为布尔结果的表达式).。exp1 and exp2 # Logical ANDexp1 or exp2 # Logical ORnot exp1 # Logical NOT.会翻译成.exp1 & exp2 # Element-wise logical ANDexp1 | exp2 # Element-wise logical OR~exp1
# Element-wise logical NOT为了熊猫。如果在执行逻辑操作的过程中,您将得到一个ValueError,则需要使用括号进行分组:(exp1) op (exp2)例如,(df['col1'] == x) & (df['col2'] == y)诸若此类。布尔索引一个常见的操作是通过逻辑条件计算布尔掩码来过滤数据。熊猫提供三操作员:&合乎逻辑,|用于逻辑或,以及~逻辑上没有。考虑以下设置:np.random.seed(0)df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))df
A B C0 5 0 31 3 7 92 3 5 23 4 7 64 8 8 1逻辑与为df上面,假设您想返回A<5和B>5的所有行。这是通过分别计算每个条件的掩码来完成的,并对它们进行处理。重载位&操作者在继续之前,请注意以下特定的文档摘录:另一个常见操作是使用布尔向量过滤数据。营办商包括:|为or, &为and,和~为not. 必须使用括号对它们进行分组。,因为默认情况下Python将计算一个表达式,如df.A > 2 & df.B < 3如df.A > (2 &
df.B) < 3,而所需的评估顺序是(df.A > 2) & (df.B <
3).因此,考虑到这一点,元素分逻辑,可以用位运算符实现。&:df['A'] < 50 False1 True2 True3 True4 FalseName: A, dtype: bool
df['B'] > 50 False1 True2 False3 True4 TrueName: B, dtype: bool(df['A'] < 5) & (df['B'] > 5)0 False1 True2 False3 True4 Falsedtype: bool接下来的过滤步骤很简单,df[(df['A'] < 5) & (df['B'] > 5)]
A B C1 3 7 93 4 7 6圆括号用于覆盖按位运算符的默认优先顺序,后者比条件运算符具有更高的优先级。<和>..见算子优先在蟒蛇的文档里。如果不使用括号,则将错误地计算表达式。例如,如果您意外地尝试了诸如df['A'] < 5 & df['B'] > 5它被解析为df['A'] < (5 & df['B']) > 5变成,df['A'] < something_you_dont_want > 5(请参阅python文档)链式算子比较),(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避免部分分组解决办法其实很简单。大多数操作符都有相应的DataFrame绑定方法。如果单个掩码是使用函数而不是条件运算符构建的,则不再需要按父母分组来指定计算顺序:df['A'].lt(5)0 True1 True2 True3 True4 FalseName: A, dtype: bool
df['B'].gt(5)0 False1 True2 False3 True4 TrueName: B, dtype: booldf['A'].lt(5) & df['B'].gt(5)0 False1 True2 False3 True4 Falsedtype: bool见灵活的比较。..总之,我们有╒════╤════════════╤════════════╕│ │ 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 C1 3 7 93 4 7 6我有过广泛记录在案query和eval在……里面熊猫动态表达评价的pd.val().operator.and_允许您以功能方式执行此操作。内部呼叫Series.__and__它对应于位操作符。import operator
operator.and_(df['A'] < 5, df['B'] > 5)# Same as,# (df['A'] < 5).__and__(df['B'] > 5) 0 False1 True2 False3 True4
Falsedtype: bool
df[operator.and_(df['A'] < 5, df['B'] > 5)]
A B C1 3 7 93 4 7 6你通常不需要这个,但是知道是有用的。概括:np.logical_and(和logical_and.reduce)另一种选择是使用np.logical_and,也不需要括号分组:np.logical_and(df['A'] < 5, df['B'] > 5)0 False1 True2 False3 True4 FalseName: A, dtype: bool
df[np.logical_and(df['A'] < 5, df['B'] > 5)]
A B C1 3 7 93 4 7 6np.logical_and是Ufunc(通用职能),而且大多数运行程序都有一个reduce方法。这意味着更容易泛化。logical_and如果你有多个面具。例如,to和掩码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 C1 3 7 93 4 7 6我知道我是在唠叨这一点,但请容忍我。这是一个非常, 非常普通初学者的错误,必须非常彻底地解释。逻辑OR为df上面,假设您想返回A=3或B=7的所有行。重载位|df['A'] == 30 False1 True2 True3 False4 FalseName: A, dtype: bool
df['B'] == 70 False1 True2 False3 True4 FalseName: B, dtype: bool(df['A'] == 3) | (df['B'] == 7)0 False1 True2 True3 True4 Falsedtype: bool
df[(df['A'] == 3) | (df['B'] == 7)]
A B C1 3 7 92 3 5 23 4 7 6如果您还没有,请阅读逻辑与以上,所有的警告都适用于此。或者,可以用df[df['A'].eq(3) | df['B'].eq(7)]
A B C1 3 7 92 3 5 23 4 7 6operator.or_打电话Series.__or__在引擎盖下面。operator.or_(df['A'] == 3, df['B'] == 7)# Same as,# (df['A'] == 3).__or__(df['B'] == 7)0 False1 True2 True3 True4
Falsedtype: bool
df[operator.or_(df['A'] == 3, df['B'] == 7)]
A B C1 3 7 92 3 5 23 4 7 6np.logical_or对于两个条件,请使用logical_or:np.logical_or(df['A'] == 3, df['B'] == 7)0 False1 True2 True3 True4 FalseName: A, dtype: bool
df[np.logical_or(df['A'] == 3, df['B'] == 7)]
A B C1 3 7 92 3 5 23 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 C1 3 7 92 3 5 23 4 7 6逻辑不戴上面具,如mask = pd.Series([True, True, False])如果您需要反转每个布尔值(因此最终结果是[False, False, True]),则可以使用以下任何方法。按位~~mask0 False1 False2 Truedtype: bool同样,表达式需要加括号。~(df['A'] == 3)0 True1 False2 False3 True4 TrueName: A, dtype: bool这内部呼叫mask.__invert__()0 False1 False2 Truedtype: bool但不要直接用。operator.inv内部呼叫__invert__在系列赛上。operator.inv(mask)0 False1 False2 Truedtype: boolnp.logical_not这是矮胖的变体。np.logical_not(mask)0 False1 False2 Truedtype: bool注:np.logical_and可以代替np.bitwise_and, logical_or带着bitwise_or,和logical_not带着invert.