当前位置: 首页 > article >正文

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 会被当作 0True 会被当作 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.anynp.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.allnp.any 也可以沿特定轴进行操作。例如:

# 是否每行的值都小于8?
np.all(x < 8, axis=1)
array([False, False,  True])

这里,第三行的所有元素都小于 8,而其他行则不是如此。

最后需要提醒一点:正如在 聚合:最小值、最大值以及所有其他内容 中提到的,Python 内置的 sumanyall 函数与 NumPy 版本的语法不同,尤其是在多维数组上使用时,可能会出错或产生意外结果。在这些示例中,请确保使用的是 np.sumnp.anynp.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 与运算符 &/| 的区别

一个常见的困惑点是关键字 andor 与运算符 &| 之间的区别。
什么时候应该用前者,什么时候用后者?

区别在于:andor 作用于整个对象,而 &| 作用于对象中的每个元素。

当你使用 andor 时,相当于让 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 = True0 = 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()

类似地,当你对一个数组进行布尔表达式运算时,应使用 |&,而不是 orand

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 比较、掩码与布尔逻辑

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

力扣HOT100之二分查找:35. 搜索插入位置

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

使用API有效率地管理Dynadot域名,查看域名市场中所售域名的详细信息

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…...

IM即时通讯软件,构建企业局域网内安全协作

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

VueScan:全能扫描,高清输出

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

PyCharm项目和文件运行时使用conda环境的教程

打开【文件】—【新建项目】 按照下图配置环境 可以看到我这个项目里&#xff0c;报错“No module named modelscope” 点击终端&#xff0c;输入命令 #显示所有的conda环境 conda env list #选择需要激活的conda环境 conda activate XXX在终端中&#xff0c;执行pip install …...

第八部分:第五节 - 生命周期与副作用 (`useEffect` Hook):组件的幕后工作

知识点&#xff1a; 组件生命周期&#xff08;挂载 Mounting, 更新 Updating, 卸载 Unmounting - 高级概念&#xff09;&#xff0c;副作用 (Side Effects)&#xff0c;useEffect Hook (用于处理副作用&#xff0c;如数据获取、订阅、DOM 操作)&#xff0c;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 的客户端&#xff0c;用于与 DeepSeek API 进行交互。它支持聊天消息完成、流式处理、错误处理以及使用高级参数配置 DeepSeekLLM。 二、Features 特征 Supports chat completion …...

Flask-Login使用示例

项目结构 首先创建以下文件结构&#xff1a; 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 引入的重要特性&#xff0c;它允许开发者在函数组件中使用状态和其他 React 特性。本文将详细介绍 6 个最常用的 React Hooks。 1. useState useState 是最常用的 Hook&#xff0c;用于在函数组件中添加 state。 import React, { useState } from…...

web第九次课后作业--SpringBoot基于mybatis实现对数据库的操作

前言 在前面我们学习MySQL数据库时&#xff0c;都是利用图形化客户端工具(如&#xff1a;idea、datagrip)&#xff0c;来操作数据库的。 在客户端工具中&#xff0c;编写增删改查的SQL语句&#xff0c;发给MySQL数据库管理系统&#xff0c;由数据库管理系统执行SQL语句并返回执…...

沪铜6月想法

市场回顾 2025年5月&#xff0c;沪铜期货主力合约价格整体呈现震荡走势。从月初到月末&#xff0c;价格在7.67-7.82万元/吨之间波动。截至5月31日&#xff0c;沪铜主力合约收盘价为7.76万元/吨。本月铜价围绕供需基本面和宏观政策预期展开波动&#xff0c;尤其在5月14日至5月1…...

网络通信核心概念全解析:从IP地址到TCP/UDP实战

一、网络基础架构三要素 1. IP地址&#xff1a;互联网的“门牌号” 本质&#xff1a;32位整数标识主机位置&#xff08;IPv4&#xff09;表示法&#xff1a;点分十进制&#xff08;如 192.168.1.1&#xff09;功能&#xff1a;全球唯一标识网络设备特殊地址&#xff1a; 127.…...

Spring 中的disposableBean介绍

在 Spring 框架中&#xff0c;DisposableBean 是一个接口&#xff0c;用于定义 Bean 在被销毁前需要执行的清理逻辑。它是 Spring 容器生命周期回调机制的一部分。 &#x1f331; 什么是 DisposableBean DisposableBean 接口是 Spring 提供的一个标准接口&#xff0c;用于通知…...

【Linux命令学习】获取cpu信息 - lscpu命令学习

lscpu命令显示的是服务器cpu架构相关信息&#xff0c;lscpu从伪文件系统(sysfs)、/proc/cpuinfo和任何可用的特定体系架构库中收集cpu架构信息。输出内容包括&#xff1a;CPU、线程、内核的数量以及非同一存储器存取节点。此外还包括关于CPU高速缓存和高速缓存共享的信息&#…...

wordpress免费主题网站

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

Go中的协程并发和并发panic处理

1 协程基础 1.1 协程定义&#xff08;Goroutine&#xff09; 概念&#xff1a;Go 语言特有的轻量级线程&#xff0c;由 Go 运行时&#xff08;runtime&#xff09;管理&#xff0c;相比系统线程&#xff08;Thread&#xff09;&#xff0c;创建和销毁成本极低&#xff0c;占用…...

Qt Creator工具编译器配置

1、打开Qt Creator&#xff0c;工具-->选项 2、选择"编译器"&#xff0c;Manual配置编译器。 初始化填入“C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\cl.exe”&#xff0c;选择64位amd64。 ABI根据msvc版本进行选择msvc2015. 3、新建项目…...

从零开始的数据结构教程(六) 贪心算法

&#x1f36c; 标题一&#xff1a;贪心核心思想——发糖果时的最优分配策略 贪心算法 (Greedy Algorithm) 是一种简单直观的算法策略。它在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望得到一个全局最优解。这就像你…...

Spring框架学习day7--SpringWeb学习(概念与搭建配置)

SpringWeb1.SpringWeb特点2.SpringWeb运行流程3.SpringWeb组件4.搭建项目结构图&#xff1a;4.1导入jar包4.2在Web.xml配置**4.2.1配置统一拦截分发器 DispatcherServlet**4.2.2开启SpringWeb注解&#xff08;spring.xml&#xff09; 5.处理类的搭建6.SpringWeb请求流程(自己理…...

打造高效多模态RAG系统:原理与评测方法详解

引言 随着信息检索与生成式AI的深度融合&#xff0c;检索增强生成&#xff08;RAG, Retrieval-Augmented Generation&#xff09; 已成为AI领域的重要技术方向。传统RAG系统主要依赖文本数据&#xff0c;但真实世界中的信息往往包含图像、表格等多模态内容。多模态RAG&#xf…...

SSM 框架核心知识详解(Spring + SpringMVC + MyBatis)

&#x1f331; 第一部分&#xff1a;Spring 核心原理与使用 1. 什么是 Spring Spring 是一个开源的 Java 企业级开发框架&#xff0c;旨在简化 Java 企业应用程序开发。它核心思想是控制反转&#xff08;IoC&#xff09;和面向切面编程&#xff08;AOP&#xff09;&#xff0…...

1.2 fetch详解

浏览器 Fetch API 详解 Fetch API 是现代浏览器提供的用于发起网络请求的接口&#xff0c;它基于 Promise 实现&#xff0c;替代了传统的 XMLHttpRequest&#xff0c;提供了更强大、更灵活的功能。 1. 基本用法 使用 fetch() 函数发起请求&#xff0c;返回一个 Promise&…...

【C#】Quartz.NET怎么动态调用方法,并且根据指定时间周期执行,动态配置类何方法以及Cron表达式,有请DeepSeek

&#x1f339;欢迎来到《小5讲堂》&#x1f339; &#x1f339;这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。&#x1f339; &#x1f339;温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01;&#…...

02 Deep learning神经网络的编程基础 逻辑回归--吴恩达

逻辑回归 逻辑回归是一种用于解决二分类任务&#xff08;如预测是否是猫咪等&#xff09;的统计学习方法。尽管名称中包含“回归”&#xff0c;但其本质是通过线性回归的变体输出概率值&#xff0c;并使用Sigmoid函数将线性结果映射到[0,1]区间。 以猫咪预测为例 假设单个样…...

Android Native 内存泄漏检测全解析:从原理到工具的深度实践

引言 Android应用的内存泄漏不仅发生在Java/Kotlin层&#xff0c;Native&#xff08;C/C&#xff09;层的泄漏同样普遍且隐蔽。由于Native内存不受Java虚拟机&#xff08;JVM&#xff09;管理&#xff0c;泄漏的内存无法通过GC自动回收&#xff0c;长期积累会导致应用内存占用…...

React---扩展补充

一些额外的扩展 4.3 高阶组件 高阶组件是参数为组件&#xff0c;返回值为新组件的函数&#xff1b; 高阶组件 本身不是一个组件&#xff0c;而是一个函数&#xff1b;其次&#xff0c;这个函数的参数是一个组件&#xff0c;返回值也是一个组件&#xff1b; import React fr…...

HTML 中 class 属性介绍、用法

1、&#x1f516; 什么是 class class 是 HTML 元素的一个核心属性&#xff0c;用来为元素指定一个或多个类名。它在网页开发中承担三大作用&#xff1a; &#x1f3a8; 连接样式&#xff08;CSS&#xff09;&#xff1a;让元素应用预定义的视觉效果⚙️ 绑定行为&#xff08…...

MySQL的并发事务问题及事务隔离级别

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