NumPy 比较、掩码与布尔逻辑
文章目录
- 比较、掩码与布尔逻辑
- 示例:统计下雨天数
- 作为通用函数(Ufuncs)的比较运算符
- 使用布尔数组
- 计数条目
- 布尔运算符
- 布尔数组作为掩码
- 使用关键字 and/or 与运算符 &/| 的区别
比较、掩码与布尔逻辑
本文介绍如何使用布尔掩码来检查和操作 NumPy 数组中的值。
当你想根据某些条件提取、修改、计数或以其他方式处理数组中的值时,就会用到掩码:例如,你可能希望统计所有大于某个值的元素,或者移除所有高于某个阈值的异常值。
在 NumPy 中,布尔掩码通常是完成此类任务最高效的方法。
示例:统计下雨天数
假设你有一组数据,表示某个城市一年中每天的降水量。
例如,这里我们将使用 Pandas 加载 2015 年西雅图的每日降雨统计数据:
import numpy as np
from vega_datasets import data# Use DataFrame operations to extract rainfall as a NumPy array
rainfall_mm = np.array(data.seattle_weather().set_index('date')['precipitation']['2015'])
len(rainfall_mm)
365
该数组包含 365 个数值,表示 2015 年 1 月 1 日至 12 月 31 日每天的降雨量(单位:毫米)。
作为初步的可视化,我们可以通过下图(使用 Matplotlib
生成)查看雨天的直方图:
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('seaborn-v0_8-whitegrid')
plt.hist(rainfall_mm, 40);
这个直方图让我们对数据有了一个大致的了解:尽管这座城市以多雨著称,但实际上 2015 年西雅图大多数日子的降雨量几乎为零。
不过,这并不能很好地展示我们想要了解的信息:比如,这一年中有多少个下雨天?下雨天的平均降水量是多少?有多少天的降水量超过了 10 毫米?
一种方法是手动回答这些问题:我们可以遍历数据,每当遇到落在某个范围内的数值时就递增计数器。
但正如本章多次讨论的那样,从编写代码和计算结果的效率来看,这种方法都非常低效。
我们在NumPy 数组上的计算:通用函数中看到,NumPy 的 ufunc 可以用来替代循环,对数组进行快速的逐元素算术运算;同样地,我们也可以使用其他 ufunc 对数组进行逐元素比较,然后操作结果来回答我们关心的问题。
我们暂且把数据放在一边,先来讨论 NumPy 中的一些通用工具,看看如何利用掩码快速回答这类问题。
作为通用函数(Ufuncs)的比较运算符
NumPy 数组上的计算:通用函数 介绍了通用函数(ufuncs),并重点讲解了算术运算符。我们看到,对数组使用 +
、-
、*
、/
等运算符会进行逐元素操作。
NumPy 还实现了诸如 <
(小于)和 >
(大于)这样的比较运算符,并将它们作为逐元素的通用函数。
这些比较运算符的结果总是一个布尔类型的数据数组。
所有六种标准的比较操作都可供使用:
x = np.array([1, 2, 3, 4, 5])
x < 3 # less than 小于
array([ True, True, False, False, False])
x > 3 # greater than 大于
array([False, False, False, True, True])
x <= 3 # less than or equal to 小于等于
array([ True, True, True, False, False])
x >= 3 # greater than or equal to 大于等于
array([False, False, True, True, True])
x != 3 # not equal 不等于
array([ True, True, False, True, True])
x == 3 # equal 等于
array([False, False, True, False, False])
也可以对两个数组进行逐元素比较,并包含复合表达式:
(2 * x) == (x ** 2) # 等式判断
array([False, True, False, False, False])
如同算术运算符一样,NumPy 中的比较运算符也是以通用函数(ufuncs)的形式实现的;例如,当你写下 x < 3
时,NumPy 在内部实际上调用的是 np.less(x, 3)
。
下表总结了常用的比较运算符及其对应的 ufunc:
运算符 | 对应的 ufunc | 运算符 | 对应的 ufunc |
---|---|---|---|
== | np.equal | != | np.not_equal |
< | np.less | <= | np.less_equal |
> | np.greater | >= | np.greater_equal |
就像算术通用函数(ufuncs)一样,这些比较运算符同样适用于任意大小和形状的数组。
下面是一个二维数组的示例:
rng = np.random.default_rng(seed=1701)
x = rng.integers(10, size=(3, 4))
x
array([[9, 4, 0, 3],[8, 6, 3, 1],[3, 7, 4, 0]])
x < 6
array([[False, True, True, True],[False, False, True, True],[ True, False, True, True]])
在每种情况下,结果都是一个布尔数组,NumPy 提供了许多直接的方法来处理这些布尔结果。
使用布尔数组
给定一个布尔数组,你可以进行许多有用的操作。
我们将使用前面创建的二维数组 x
进行演示:
print(x)
[[9 4 0 3][8 6 3 1][3 7 4 0]]
计数条目
要统计布尔数组中 True
条目的数量,可以使用 np.count_nonzero
:
# 小于6的条目数
np.count_nonzero(x < 6)
8
我们可以看到,有八个数组元素小于 6。
另一种获取此信息的方法是使用 np.sum
;在这种情况下,False
会被当作 0
,True
会被当作 1
:
np.sum(x < 6)
np.int64(8)
np.sum
的好处在于,和其他 NumPy 聚合函数一样,这种求和操作也可以沿着行或列进行:
# 每一行小于6的条目数
np.sum(x < 6, axis=1)
array([3, 2, 3])
这将统计矩阵每一行中小于 6 的值的数量。
如果我们想快速检查某一行是否有任意值为 True
,或者所有值都为 True
,可以使用(你猜对了)np.any
或 np.all
:
# 是否有大于8的值?
np.any(x > 8)
np.True_
# 是否有小于0的值?
np.any(x < 0)
np.False_
# 所有值都小于10吗?
np.all(x < 10)
np.True_
# 所有值都等于6?
np.all(x == 6)
np.False_
np.all
和 np.any
也可以沿特定轴进行操作。例如:
# 是否每行的值都小于8?
np.all(x < 8, axis=1)
array([False, False, True])
这里,第三行的所有元素都小于 8,而其他行则不是如此。
最后需要提醒一点:正如在 聚合:最小值、最大值以及所有其他内容 中提到的,Python 内置的 sum
、any
和 all
函数与 NumPy 版本的语法不同,尤其是在多维数组上使用时,可能会出错或产生意外结果。在这些示例中,请确保使用的是 np.sum
、np.any
和 np.all
!
布尔运算符
我们已经看到如何统计降雨量小于 20 毫米的天数,或者降雨量大于 10 毫米的天数。 但如果我们想知道降雨量大于 10 毫米且小于 20 毫米的天数有多少天呢?这时可以用 Python 的按位逻辑运算符 &
、|
、^
和 ~
来实现。 与标准算术运算符类似,NumPy 也重载了这些运算符,使其可以对(通常是布尔型)数组进行逐元素操作。
例如,我们可以这样解决这类复合问题:
np.sum((rainfall_mm > 10) & (rainfall_mm < 20))
np.int64(16)
这告诉我们有 16 天的降雨量在 10 到 20 毫米之间。
这里的括号非常重要。由于运算符优先级规则,如果去掉括号,这个表达式会被如下方式计算,这将导致错误:
rainfall_mm > (10 & rainfall_mm) < 20
Let’s demonstrate a more complicated expression. Using De Morgan’s laws, we can compute the same result in a different manner:
让我们展示一个更复杂的表达方式——利用德摩根定律,用另一种方式得出相同的结果:
np.sum(~( (rainfall_mm <= 10) | (rainfall_mm >= 20) ))
np.int64(16)
将比较运算符与布尔运算符结合应用于数组,可以实现高效且多样的逻辑操作。
下表总结了按位布尔运算符及其对应的通用函数 ufunc:
运算符 | 对应的 ufunc | 运算符 | 对应的 ufunc |
---|---|---|---|
& | np.bitwise_and | | | np.bitwise_or |
^ | np.bitwise_xor | ~ | np.bitwise_not |
利用这些工具,我们可以开始回答关于天气数据的许多问题。
以下是结合掩码与聚合操作时可以计算的一些结果示例:
print("Number days without rain: ", np.sum(rainfall_mm == 0))
print("Number days with rain: ", np.sum(rainfall_mm != 0))
print("Days with more than 10 mm: ", np.sum(rainfall_mm > 10))
print("Rainy days with < 5 mm: ", np.sum((rainfall_mm > 0) &(rainfall_mm < 5)))
Number days without rain: 221
Number days with rain: 144
Days with more than 10 mm: 34
Rainy days with < 5 mm: 83
布尔数组作为掩码
在前一节中,我们介绍了如何直接对布尔数组进行聚合计算。
更强大的用法是将布尔数组用作掩码,从而选择数据中的特定子集。让我们回到之前的 x 数组:
x
array([[9, 4, 0, 3],[8, 6, 3, 1],[3, 7, 4, 0]])
假设我们想要获取数组中所有小于 5 的值组成的数组。正如我们之前看到的,我们可以很容易地为这个条件获得一个布尔数组:
x < 5
array([[False, True, True, True],[False, False, True, True],[ True, False, True, True]])
现在,要从数组中选取这些值,我们只需用这个布尔数组进行索引;这被称为掩码操作(masking operation):
x[x < 5]
array([4, 0, 3, 3, 1, 3, 4, 0])
返回的是一个一维数组,包含所有满足该条件的值;换句话说,就是所有在掩码数组中对应位置为 True 的值。
随后,我们可以对这些值进行任意操作。 例如,我们可以对西雅图降雨数据计算一些相关统计量:
# construct a mask of all rainy days
rainy = (rainfall_mm > 0)# construct a mask of all summer days (June 21st is the 172nd day)
days = np.arange(365)
summer = (days > 172) & (days < 262)print("Median precip on rainy days in 2015 (mm): ",np.median(rainfall_mm[rainy]))
print("Median precip on summer days in 2015 (mm): ",np.median(rainfall_mm[summer]))
print("Maximum precip on summer days in 2015 (mm): ",np.max(rainfall_mm[summer]))
print("Median precip on non-summer rainy days (mm):",np.median(rainfall_mm[rainy & ~summer]))
Median precip on rainy days in 2015 (mm): 3.8
Median precip on summer days in 2015 (mm): 0.0
Maximum precip on summer days in 2015 (mm): 32.5
Median precip on non-summer rainy days (mm): 4.1
通过结合布尔运算、掩码操作和聚合操作,我们可以非常快速地回答关于数据集的这类问题。
使用关键字 and/or 与运算符 &/| 的区别
一个常见的困惑点是关键字 and
和 or
与运算符 &
和 |
之间的区别。
什么时候应该用前者,什么时候用后者?
区别在于:and
和 or
作用于整个对象,而 &
和 |
作用于对象中的每个元素。
当你使用 and
或 or
时,相当于让 Python 把整个对象当作一个布尔实体来处理。
在 Python 中,所有非零整数都会被判断为 True
。因此:
bool(42), bool(0)
(True, False)
bool(42 and 0)
False
bool(42 or 0)
True
当你对整数使用 &
和 |
时,表达式会作用于元素的位表示,对组成该数字的每一位分别执行按位与或按位或操作:
bin(42)
'0b101010'
bin(59)
'0b111011'
bin(42 & 59)
'0b101010'
bin(42 | 59)
'0b111011'
注意,二进制表示的对应位会逐一比较,从而得出结果。
当你在 NumPy 中拥有一个布尔值数组时,可以将其视为一串比特,其中 1 = True
,0 = False
,而 &
和 |
的操作方式与前面的示例类似:
A = np.array([1, 0, 1, 0, 1, 0], dtype=bool)
B = np.array([1, 1, 1, 0, 1, 1], dtype=bool)
A | B
array([ True, True, True, False, True, True])
但是如果你对这些数组使用 or
,它会尝试判断整个数组对象的真值,这并不是一个明确定义的值:
A or B
---------------------------------------------------------------------------ValueError Traceback (most recent call last)Cell In[38], line 1
----> 1 A or BValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
类似地,当你对一个数组进行布尔表达式运算时,应使用 |
或 &
,而不是 or
或 and
:
x = np.arange(10)
(x > 4) & (x < 8)
array([False, False, False, False, False, True, True, True, False,False])
尝试对整个数组求真或求假会导致和之前一样的 ValueError
错误:
(x > 4) and (x < 8)
---------------------------------------------------------------------------ValueError Traceback (most recent call last)Cell In[40], line 1
----> 1 (x > 4) and (x < 8)ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
相关文章:

NumPy 比较、掩码与布尔逻辑
文章目录 比较、掩码与布尔逻辑示例:统计下雨天数作为通用函数(Ufuncs)的比较运算符使用布尔数组计数条目布尔运算符 布尔数组作为掩码使用关键字 and/or 与运算符 &/| 的区别 比较、掩码与布尔逻辑 本文介绍如何使用布尔掩码来检查和操…...

力扣HOT100之二分查找:35. 搜索插入位置
这道题属于是二分查找的入门题了,我依稀记得一些二分查找的编码要点,但是最后还是写出了一个死循环,无语(ˉ▽ˉ;)…又回去看了下自己当时的博客和卡哥的视频,这才发现自己分情况只分了两种,最后导致死循环…...

使用API有效率地管理Dynadot域名,查看域名市场中所售域名的详细信息
关于Dynadot Dynadot是通过ICANN认证的域名注册商,自2002年成立以来,服务于全球108个国家和地区的客户,为数以万计的客户提供简洁,优惠,安全的域名注册以及管理服务。 Dynadot平台操作教程索引(包括域名邮…...

IM即时通讯软件,构建企业局域网内安全协作
安全与权限:协同办公的企业级保障 在协同办公场景中,BeeWorks 将安全机制贯穿全流程。文件在局域网内传输与存储时均采用加密处理,企业网盘支持水印预览、离线文档权限回收等功能,防止敏感资料外泄;多人在线编辑文档时…...

VueScan:全能扫描,高清输出
在数字化办公和图像处理的领域,扫描仪扮演着不可或缺的角色。无论是文档的数字化存档、照片的高清复制,还是创意项目的素材采集,一款性能卓越、操作便捷的扫描软件能大幅提升工作效率和成果质量。VueScan正是这样一款集多功能于一身的扫描仪软…...

PyCharm项目和文件运行时使用conda环境的教程
打开【文件】—【新建项目】 按照下图配置环境 可以看到我这个项目里,报错“No module named modelscope” 点击终端,输入命令 #显示所有的conda环境 conda env list #选择需要激活的conda环境 conda activate XXX在终端中,执行pip install …...
第八部分:第五节 - 生命周期与副作用 (`useEffect` Hook):组件的幕后工作
知识点: 组件生命周期(挂载 Mounting, 更新 Updating, 卸载 Unmounting - 高级概念),副作用 (Side Effects),useEffect Hook (用于处理副作用,如数据获取、订阅、DOM 操作),useEffect 的依赖数组…...
docker 搭建php 开发环境 添加扩展redis、swoole、xdebug(2)
3、创建compose 的yml文件 version: "3.9" services:#配置nginxnginx:#镜像名称 nginx:latestimage: nginx#自定义容器的名称#container_name: c_nginxports:- "80:80"#lnmp目录和容器的/usr/share/nginx/html目录进行绑定,设置rw权限#将宿主机的~/lnmp/…...

DeepSwiftSeek 开源软件 |用于 DeepSeek LLM 模型的 Swift 客户端 |轻量级和高效的 DeepSeek 核心功能通信
一、软件介绍 文末提供程序和源码下载 DeepSeek Swift SDK 是一个轻量级且高效的基于 Swift 的客户端,用于与 DeepSeek API 进行交互。它支持聊天消息完成、流式处理、错误处理以及使用高级参数配置 DeepSeekLLM。 二、Features 特征 Supports chat completion …...

Flask-Login使用示例
项目结构 首先创建以下文件结构: flask_login_use/ ├── app.py ├── models.py ├── requirements.txt └── templates/├── base.html├── index.html├── login.html├── register.html└── profile.html1. requirements.txt Flask2.3.3 Fl…...
React Hooks 基础指南
React Hooks 是 React 16.8 引入的重要特性,它允许开发者在函数组件中使用状态和其他 React 特性。本文将详细介绍 6 个最常用的 React Hooks。 1. useState useState 是最常用的 Hook,用于在函数组件中添加 state。 import React, { useState } from…...

web第九次课后作业--SpringBoot基于mybatis实现对数据库的操作
前言 在前面我们学习MySQL数据库时,都是利用图形化客户端工具(如:idea、datagrip),来操作数据库的。 在客户端工具中,编写增删改查的SQL语句,发给MySQL数据库管理系统,由数据库管理系统执行SQL语句并返回执…...
沪铜6月想法
市场回顾 2025年5月,沪铜期货主力合约价格整体呈现震荡走势。从月初到月末,价格在7.67-7.82万元/吨之间波动。截至5月31日,沪铜主力合约收盘价为7.76万元/吨。本月铜价围绕供需基本面和宏观政策预期展开波动,尤其在5月14日至5月1…...
网络通信核心概念全解析:从IP地址到TCP/UDP实战
一、网络基础架构三要素 1. IP地址:互联网的“门牌号” 本质:32位整数标识主机位置(IPv4)表示法:点分十进制(如 192.168.1.1)功能:全球唯一标识网络设备特殊地址: 127.…...
Spring 中的disposableBean介绍
在 Spring 框架中,DisposableBean 是一个接口,用于定义 Bean 在被销毁前需要执行的清理逻辑。它是 Spring 容器生命周期回调机制的一部分。 🌱 什么是 DisposableBean DisposableBean 接口是 Spring 提供的一个标准接口,用于通知…...
【Linux命令学习】获取cpu信息 - lscpu命令学习
lscpu命令显示的是服务器cpu架构相关信息,lscpu从伪文件系统(sysfs)、/proc/cpuinfo和任何可用的特定体系架构库中收集cpu架构信息。输出内容包括:CPU、线程、内核的数量以及非同一存储器存取节点。此外还包括关于CPU高速缓存和高速缓存共享的信息&#…...

wordpress免费主题网站
这是一款WordPress主题,由jianzhanpress开发,可以免费下载。专为中小微企业设计,提供专业的网站建设、网站运营维护、网站托管和网站优化等服务。主题设计简约、现代,适合多种行业需求。 主要特点: 多样化展示&#…...

Go中的协程并发和并发panic处理
1 协程基础 1.1 协程定义(Goroutine) 概念:Go 语言特有的轻量级线程,由 Go 运行时(runtime)管理,相比系统线程(Thread),创建和销毁成本极低,占用…...

Qt Creator工具编译器配置
1、打开Qt Creator,工具-->选项 2、选择"编译器",Manual配置编译器。 初始化填入“C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\cl.exe”,选择64位amd64。 ABI根据msvc版本进行选择msvc2015. 3、新建项目…...
从零开始的数据结构教程(六) 贪心算法
🍬 标题一:贪心核心思想——发糖果时的最优分配策略 贪心算法 (Greedy Algorithm) 是一种简单直观的算法策略。它在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望得到一个全局最优解。这就像你…...

Spring框架学习day7--SpringWeb学习(概念与搭建配置)
SpringWeb1.SpringWeb特点2.SpringWeb运行流程3.SpringWeb组件4.搭建项目结构图:4.1导入jar包4.2在Web.xml配置**4.2.1配置统一拦截分发器 DispatcherServlet**4.2.2开启SpringWeb注解(spring.xml) 5.处理类的搭建6.SpringWeb请求流程(自己理…...

打造高效多模态RAG系统:原理与评测方法详解
引言 随着信息检索与生成式AI的深度融合,检索增强生成(RAG, Retrieval-Augmented Generation) 已成为AI领域的重要技术方向。传统RAG系统主要依赖文本数据,但真实世界中的信息往往包含图像、表格等多模态内容。多模态RAG…...
SSM 框架核心知识详解(Spring + SpringMVC + MyBatis)
🌱 第一部分:Spring 核心原理与使用 1. 什么是 Spring Spring 是一个开源的 Java 企业级开发框架,旨在简化 Java 企业应用程序开发。它核心思想是控制反转(IoC)和面向切面编程(AOP)࿰…...
1.2 fetch详解
浏览器 Fetch API 详解 Fetch API 是现代浏览器提供的用于发起网络请求的接口,它基于 Promise 实现,替代了传统的 XMLHttpRequest,提供了更强大、更灵活的功能。 1. 基本用法 使用 fetch() 函数发起请求,返回一个 Promise&…...

【C#】Quartz.NET怎么动态调用方法,并且根据指定时间周期执行,动态配置类何方法以及Cron表达式,有请DeepSeek
🌹欢迎来到《小5讲堂》🌹 🌹这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解。🌹 🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!&#…...

02 Deep learning神经网络的编程基础 逻辑回归--吴恩达
逻辑回归 逻辑回归是一种用于解决二分类任务(如预测是否是猫咪等)的统计学习方法。尽管名称中包含“回归”,但其本质是通过线性回归的变体输出概率值,并使用Sigmoid函数将线性结果映射到[0,1]区间。 以猫咪预测为例 假设单个样…...
Android Native 内存泄漏检测全解析:从原理到工具的深度实践
引言 Android应用的内存泄漏不仅发生在Java/Kotlin层,Native(C/C)层的泄漏同样普遍且隐蔽。由于Native内存不受Java虚拟机(JVM)管理,泄漏的内存无法通过GC自动回收,长期积累会导致应用内存占用…...
React---扩展补充
一些额外的扩展 4.3 高阶组件 高阶组件是参数为组件,返回值为新组件的函数; 高阶组件 本身不是一个组件,而是一个函数;其次,这个函数的参数是一个组件,返回值也是一个组件; import React fr…...
HTML 中 class 属性介绍、用法
1、🔖 什么是 class class 是 HTML 元素的一个核心属性,用来为元素指定一个或多个类名。它在网页开发中承担三大作用: 🎨 连接样式(CSS):让元素应用预定义的视觉效果⚙️ 绑定行为(…...

MySQL的并发事务问题及事务隔离级别
一、并发事务问题 1). 赃读:一个事务读到另外一个事务还没有提交的数据。 比如 B 读取到了 A 未提交的数据。 2). 不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。 事务 A 两次读取同一条记录&…...