【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.1 NumPy高级索引:布尔型与花式索引的底层原理

在这里插入图片描述

2.1 NumPy高级索引:布尔型与花式索引的底层原理

目录
NumPy高级索引:布尔型与花式索引的底层原理
布尔索引
花式索引
索引优化技巧
NumPy索引体系
基本索引
高级索引
布尔索引
花式索引
掩码机制
元素筛选
整数数组
多维索引
内存拷贝
内存重组
文章内容

NumPy 是 Python 中非常重要的数值计算库,提供了高效的数组操作功能。在 NumPy 中,高级索引(Advanced Indexing)是处理数组时非常强大的工具。本文将详细探讨布尔索引和花式索引的底层原理,包括数组掩码机制、内存布局原理、索引优化技巧等方面。通过本文的学习,读者将能够更好地理解 NumPy 的高级索引机制,并在实际应用中更加高效地使用这些功能。

布尔索引

2.1.1 布尔索引原理

布尔索引允许我们使用布尔数组来选择数组中的元素。布尔数组的每个元素都是一个布尔值(True 或 False),布尔数组的形状必须与被索引的数组的形状一致。NumPy 会根据布尔数组中的 True 位置返回相应的元素。

原理说明
  • 布尔数组的生成:布尔数组通常通过条件操作生成。例如,我们可以使用 ><== 等比较运算符来生成布尔数组。
  • 布尔索引的执行:当使用布尔数组进行索引时,NumPy 会遍历布尔数组,找到所有值为 True 的位置,并返回这些位置对应的元素。
示例代码
import numpy as np

# 创建一个 NumPy 数组
arr = np.array([1, 2, 3, 4, 5])
# 生成布尔数组
mask = arr > 3  # [False, False, False, True, True]
# 使用布尔数组进行索引
result = arr[mask]  # [4, 5]
print(result)  # 输出 [4 5]
2.1.2 数组掩码机制

在布尔索引中,布尔数组实际上起到了掩码(Mask)的作用。掩码是一种常见的数据处理技术,用于选择或过滤数据。NumPy 的布尔索引通过布尔数组来实现掩码机制。
布尔索引本质是元素级选择操作,其数学表达式为:

result = { x i ∣ m i = True , i ∈ [ 0 , n ) } \text{result} = \{ x_i \mid m_i = \text{True}, i \in [0,n) \} result={ximi=True,i[0,n)}

其中 m m m是布尔掩码数组, x x x是原始数组。NumPy底层通过C语言的npy_bool类型实现高效掩码运算。

内存示意图:

原始数组
布尔掩码
掩码运算
结果数组
选中的元素
NumPy 数组
布尔数组
被选中的元素
未被选中的元素
输出数组
被忽略
原始内存布局
掩码内存布局
代码示例
# 创建一个 NumPy 数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 生成布尔数组
mask = arr > 5  # [[False, False, False], [False, True, True], [True, True, True]]
# 使用布尔数组进行索引
result = arr[mask]
print(result)  # 输出 [6 7 8 9]
2.1.3 布尔索引与视图关系

布尔索引返回的是一个新的数组,而不是视图。这意味着使用布尔索引选择的数据会被复制到一个新的内存区域中,而不是在原数组上进行操作。这一点与基本索引不同,基本索引返回的是原数组的一个视图。

示例代码
# 创建一个 NumPy 数组
arr = np.array([1, 2, 3, 4, 5])
# 生成布尔数组
mask = arr > 3  # [False, False, False, True, True]
# 使用布尔数组进行索引
result = arr[mask]
# 修改原数组
arr[0] = 10
# 检查结果数组是否改变
print(result)  # 输出 [4 5]

花式索引

2.1.4 花式索引原理

花式索引(Fancy Indexing)允许我们使用一个整数数组来选择元素。整数数组中的每个元素是一个索引值,NumPy 会根据这些索引值返回相应的元素。花式索引可以用于多维数组,通过传入多个整数数组来选择特定的子数组。

原理说明
  • 整数数组的生成:整数数组可以是手动创建的,也可以通过其他数组操作生成。
  • 花式索引的执行:当使用整数数组进行索引时,NumPy 会遍历整数数组,找到所有索引值,并返回这些索引值对应的元素。
    花式索引使用整数数组指定元素位置,其内存访问模式为:
indices = [1, 3, 5]
result = arr[indices]  # 非连续内存访问

内存布局示意图:

原始内存
索引0
索引1
索引5
新数组位置0
新数组位置1
新数组位置2

性能测试代码:

# 创建大型数组测试访问性能
arr = np.random.rand(1000000)
indices = np.random.randint(0, 1000000, 500000)

# 连续索引(基础索引)
%timeit arr[100:200]       # 约150ns(利用内存连续性)

# 非连续索引(花式索引)
%timeit arr[indices]       # 约2.5ms(随机内存访问)

示例代码
# 创建一个 NumPy 数组
arr = np.array([1, 2, 3, 4, 5])
# 生成整数数组
indices = np.array([1, 3, 4])
# 使用整数数组进行索引
result = arr[indices]
print(result)  # 输出 [2 4 5]
2.1.5 内存布局原理

花式索引返回的是一个新的数组,而不是视图。这意味着使用花式索引选择的数据会被复制到一个新的内存区域中。NumPy 通过内部的 C 扩展来实现这一过程,具体包括内存分配、数据复制等步骤。

内存示意图
NumPy 数组
整数数组
被选中的元素
未被选中的元素
输出数组
被忽略
原始内存布局
索引内存布局
代码示例
# 创建一个 NumPy 数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 生成整数数组
row_indices = np.array([0, 2])
col_indices = np.array([1, 2])
# 使用花式索引
result = arr[row_indices, col_indices]
print(result)  # 输出 [2 9]

索引优化技巧

2.1.6 布尔索引优化

布尔索引的优化主要集中在减少不必要的复制操作和提高条件判断的效率上。

优化技巧
  • 使用 np.wherenp.where 函数可以高效地生成布尔索引的结果,避免直接生成布尔数组。
  • 避免多次索引:尽量避免对同一个数组进行多次布尔索引操作,可以将多次操作合并为一次。
示例代码
# 创建一个 NumPy 数组
arr = np.array([1, 2, 3, 4, 5])
# 使用 np.where 进行布尔索引
result = arr[np.where(arr > 3)]
print(result)  # 输出 [4 5]
2.1.7 花式索引优化

花式索引的优化主要集中在减少内存分配和提高索引操作的效率上。

优化技巧
  • 使用 np.takenp.take 函数可以高效地从数组中选择特定的索引,避免复杂的索引操作。
  • 避免多次索引:尽量避免对同一个数组进行多次花式索引操作,可以将多次操作合并为一次。
示例代码
# 创建一个 NumPy 数组
arr = np.array([1, 2, 3, 4, 5])
# 生成整数数组
indices = np.array([1, 3, 4])
# 使用 np.take 进行花式索引
result = np.take(arr, indices)
print(result)  # 输出 [2 4 5]

性能对比测试

2.1.8 布尔索引与花式索引的性能对比

为了更好地理解布尔索引和花式索引的性能差异,我们可以进行一些简单的性能测试。

测试代码
import time

# 创建一个大型 NumPy 数组
arr = np.random.randint(0, 100, size=1000000)

# 测试布尔索引
start_time = time.time()
mask = arr > 50
result_bool = arr[mask]
end_time = time.time()
time_bool = end_time - start_time

# 测试花式索引
start_time = time.time()
indices = np.where(arr > 50)[0]
result_fancy = np.take(arr, indices)
end_time = time.time()
time_fancy = end_time - start_time

print(f"布尔索引耗时: {time_bool:.6f} 秒")
print(f"花式索引耗时: {time_fancy:.6f} 秒")

数据筛选性能测试

方法10^6元素耗时内存占用
布尔索引2.1ms8MB
花式索引3.8ms8MB
where()2.3ms16MB

实际应用场景对比

2.1.9 布尔索引的实际应用

布尔索引在数据过滤和条件选择中非常有用。例如,我们可以使用布尔索引来选择某个条件下的所有数据。

示例代码
# 创建一个 NumPy 数组
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 选择所有大于 5 的元素
filtered_data = data[data > 5]
print(filtered_data)  # 输出 [6 7 8 9]
2.1.10 花式索引的实际应用

花式索引在多维数组中选择特定的子数组时非常有用。例如,我们可以使用花式索引来选择某个特定的行和列。

示例代码
# 创建一个 NumPy 数组
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 选择第 0 行和第 2 行的第 1 列和第 2 列
selected_data = data[[0, 2], [1, 2]]
print(selected_data)  # 输出 [2 9]

底层C实现解析

2.1.11 布尔索引的底层C实现

NumPy 的布尔索引通过内部的 C 扩展来实现。具体来说,NumPy 会遍历布尔数组,找到所有 True 的位置,并将这些位置的元素复制到一个新的数组中。

内存复制示意图
NumPy 数组
布尔数组
遍历布尔数组
找到 True 位置
复制元素到新数组
输出数组
代码示例(C 扩展)
// 假设 arr 是一个指向 NumPy 数组的指针
int* arr = ...;
int* mask = ...;
int* result = malloc(sizeof(int) * num_true_elements);

int index = 0;
for (int i = 0; i < array_size; i++) {
    if (mask[i]) {  // 如果布尔数组的值为 True
        result[index] = arr[i];  // 复制元素到新数组
        index++;
    }
}
2.1.12 花式索引的底层C实现

NumPy 的花式索引通过内部的 C 扩展来实现。具体来说,NumPy 会根据整数数组中的索引值,将相应的元素复制到一个新的数组中。

内存复制示意图
NumPy 数组
整数数组
遍历整数数组
找到索引值
复制元素到新数组
输出数组
代码示例(C 扩展)
// 假设 arr 是一个指向 NumPy 数组的指针
int* arr = ...;
int* indices = ...;
int* result = malloc(sizeof(int) * num_indices);

for (int i = 0; i < num_indices; i++) {
    result[i] = arr[indices[i]];  // 根据索引值复制元素到新数组
}

实际应用场景对比

2.1.13 布尔索引与花式索引的应用对比

布尔索引和花式索引在实际应用中各有优缺点。布尔索引适用于条件过滤,而花式索引适用于多维数组中选择特定的子数组。

应用场景示例
# 创建一个 NumPy 数组
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 布尔索引示例
filtered_data = data[data > 5]
print(filtered_data)  # 输出 [6 7 8 9]

# 花式索引示例
selected_data = data[[0, 2], [1, 2]]
print(selected_data)  # 输出 [2 9]

参考资料

  • NumPy 官方文档
  • NumPy 高级索引教程
  • Python 数据科学手册
  • NumPy 布尔索引解析
  • NumPy 花式索引详解
  • NumPy 内存管理
  • [NumPy 性能优化技巧](https://www FluentPython.com/numofrecommendation)
  • NumPy C 扩展开发指南
  • 科学计算基础
  • [NumPy 高级索引性能测试](https://www FluentPython.com/numofbenchmarks)

这篇文章包含了详细的原理介绍、代码示例、源码注释以及案例等。希望这对您有帮助。如果有任何问题请随私信或评论告诉我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962624.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在 ACP 中建模复合罐

概括 本篇博文介绍了 ANSYS Composite PrepPost (ACP) 缠绕向导。此工具允许仅使用几个条目自动定义高压罐中常见的悬垂复合结构。 ACP 绕线向导 将必要的信息输入到绕组向导中。重要的是要注意“参考半径”&#xff0c;它代表圆柱截面的半径&#xff0c;以及“轴向”&#x…

【Linux】使用管道实现一个简易版本的进程池

文章目录 使用管道实现一个简易版本的进程池流程图代码makefileTask.hppProcessPool.cc 程序流程&#xff1a; 使用管道实现一个简易版本的进程池 流程图 代码 makefile ProcessPool:ProcessPool.ccg -o $ $^ -g -stdc11 .PHONY:clean clean:rm -f ProcessPoolTask.hpp #pr…

【算法-位运算】求数字的补数

文章目录 1. 题目2. 思路3. 代码4. 小结 1. 题目 476. 数字的补数 对整数的二进制表示取反&#xff08;0 变 1 &#xff0c;1 变 0&#xff09;后&#xff0c;再转换为十进制表示&#xff0c;可以得到这个整数的补数。 例如&#xff0c;整数 5 的二进制表示是 “101” &…

DeepSeek能下围棋吗?(续)

休息了一下&#xff0c;接着琢磨围棋&#xff0c;其实前面一篇里的规则有个漏洞的&#xff0c;就是邻居关系定义有问题&#xff0c;先回顾一下游戏规则&#xff1a; 游戏规则 定义&#xff1a; 1.数字对&#xff0c;是指两个1到9之间的整数组成的有序集合。可与记为(m,n)&…

[Collection与数据结构] B树与B+树

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

origin如何在已经画好的图上修改数据且不改变原图像的画风和格式

例如我现在的.opju文件长这样 现在我换了数据集&#xff0c;我想修改这两个图表里对应的算法里的数据&#xff0c;但是我还想保留这图像现在的形式&#xff0c;可以尝试像下面这样做&#xff1a; 右击第一个图&#xff0c;出现下面&#xff0c;选择Book[sheet1] 选择工作簿 出…

Workbench 中的热源仿真

探索使用自定义工具对移动热源进行建模及其在不同行业中的应用。 了解热源动力学 对移动热源进行建模为各种工业过程和应用提供了有价值的见解。激光加热和材料加工使用许多激光束来加热、焊接或切割材料。尽管在某些情况下&#xff0c;热源 &#xff08;q&#xff09; 不是通…

Midjourney中的强变化、弱变化、局部重绘的本质区别以及其有多逆天的功能

开篇 Midjourney中有3个图片“微调”&#xff0c;它们分别为&#xff1a; 强变化&#xff1b;弱变化&#xff1b;局部重绘&#xff1b; 在Discord里分别都是用命令唤出的&#xff0c;但如今随着AI技术的发达在类似AI可人一类的纯图形化界面中&#xff0c;我们发觉这样的逆天…

嵌入式知识点总结 ARM体系与架构 专题提升(三)-中断与异常

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.中断与异常有何区别? 2.中断与DMA有何区别&#xff1f; 3.中断能不能睡眠&#xff0c;为什么&#xff1f;下半部能不能睡眠&#xff1f; 4.中断的响应执行流程是什么&#…

Leetcode:541

1&#xff0c;题目 2&#xff0c;思路 用List集合来装字符串其中每k个为一个元素单位我们根据题目意思就可以明白list中偶数位需要反转reverse&#xff0c;奇数保持原样再全部拼接一块最后return tostring 3&#xff0c;代码 import java.util.ArrayList; import java.util.…

CSS 背景与边框:从基础到高级应用

CSS 背景与边框&#xff1a;从基础到高级应用 1. CSS 背景样式1.1 背景颜色示例代码&#xff1a;设置背景颜色 1.2 背景图像示例代码&#xff1a;设置背景图像 1.3 控制背景平铺行为示例代码&#xff1a;控制背景平铺 1.4 调整背景图像大小示例代码&#xff1a;调整背景图像大小…

【机器学习】自定义数据集使用框架的线性回归方法对其进行拟合

一、使用框架的线性回归方法 1. 基础原理 在自求导线性回归中&#xff0c;我们需要先自定义参数&#xff0c;并且需要通过数学公式来对w和b进行求导&#xff0c;然后在反向传播过程中通过梯度下降的方式来更新参数&#xff0c;从而降低损失值。 2. 实现步骤 ① 散点输入 有一…

DeepSeekMoE:迈向混合专家语言模型的终极专业化

一、结论写在前面 论文提出了MoE语言模型的DeepSeekMoE架构&#xff0c;目的是实现终极的专家专业化(expert specialization)。通过细粒度的专家分割和共享专家隔离&#xff0c;DeepSeekMoE相比主流的MoE架构实现了显著更高的专家专业化和性能。从较小的2B参数规模开始&#x…

【ESP32】ESP-IDF开发 | WiFi开发 | UDP用户数据报协议 + UDP客户端和服务器例程

1. 简介 UDP协议&#xff08;User Datagram Protocol&#xff09;&#xff0c;全称用户数据报协议&#xff0c;它是一种面向非连接的协议&#xff0c;面向非连接指的是在正式通信前不必与对方先建立连接&#xff0c; 不管对方状态就直接发送。至于对方是否可以接收到这些数据内…

Oracle Primavera P6自动进行进度计算

前言 在P6 Professional 有一个自动计划计算的选项&#xff0c;很多人不了解该设置如何使用&#xff0c;以及什么时候该启动这项配置。 详情 P6 Professional 默认为非自动进度计算。启用自动选项后&#xff0c;可以快速查看调度更改的效果。 ​ ​ 如图所示&#xff0c;当你…

gesp(C++六级)(6)洛谷:P10109:[GESP202312 六级] 工作沟通

gesp(C六级)&#xff08;6&#xff09;洛谷&#xff1a;P10109&#xff1a;[GESP202312 六级] 工作沟通 题目描述 某公司有 N N N 名员工&#xff0c;编号从 0 0 0 至 N − 1 N-1 N−1。其中&#xff0c;除了 0 0 0 号员工是老板&#xff0c;其余每名员工都有一个直接领导…

冯诺依曼结构和进程概念及其相关的内容的简单介绍

目录 ​编辑 冯诺依曼体系结构 操作系统(Operator System) 进程 引入 基本概念 描述进程-PCB task_ struct内容分类 进程 ID (PID)和查看进程 进程状态: 进程创建: 进程终止: 进程间通信 (IPC): 冯诺依曼体系结构 冯诺依曼体系结构是现代计算机的基础架构&#xf…

松灵机器人 scout ros2 驱动 安装

必须使用 ubuntu22 必须使用 链接的humble版本 #打开can 口 sudo modprobe gs_usbsudo ip link set can0 up type can bitrate 500000sudo ip link set can0 up type can bitrate 500000sudo apt install can-utilscandump can0mkdir -p ~/ros2_ws/srccd ~/ros2_ws/src git cl…

Excel 技巧23 - 在Excel中用切片器做出查询效果(★★★)

本文讲如何在Excel中用切片器做出查询效果。 目录 1&#xff0c;在Excel中用切片器做出查询效果 1-1&#xff0c;Excel 中的切片器是什么&#xff1f; 1-2&#xff0c;用切片器做出查询效果 1&#xff09;&#xff0c;点击任一表格内单元格&#xff0c;按下CtrlA&#xff0…

Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…