NumPy 切片和索引(建议收藏)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在数据科学和数值计算领域,NumPy 是 Python 生态中最基础且强大的库之一。它提供了高性能的多维数组对象,以及丰富的数学函数与工具,让开发者能够高效地处理复杂的数据操作。然而,要真正掌握 NumPy 的核心能力,理解其 切片和索引 机制至关重要。无论是提取特定数据、筛选子集,还是进行复杂的数据变换,切片和索引都是不可或缺的“瑞士军刀”。本文将从基础到进阶,结合生动的比喻和实战案例,帮助读者系统性地掌握这一主题。


一维数组的索引与切片

基础索引:直接定位元素

在 NumPy 中,数组的索引与 Python 列表类似,但功能更强大。对于一维数组,索引从 0 开始,负数索引则从末尾倒数。

示例代码

import numpy as np  
arr = np.array([10, 20, 30, 40, 50])  

print(arr[0])  # 输出 10  

print(arr[-1])  # 输出 50  

比喻:可以将数组想象成一个书架,每个元素是书本,索引就是书本的编号。例如,arr[2] 就是取第三本书(索引从 0 开始)。


切片:提取连续片段

切片允许我们通过 start:endstart:end:step 的格式提取子数组。默认情况下,start 包含在内,end 不包含在内。

示例代码

print(arr[0:3])  # 输出 [10 20 30]  

print(arr[:3])  # 输出 [10 20 30]  

print(arr[-3:])  # 输出 [30 40 50]  

print(arr[::2])  # 输出 [10 30 50]  

关键点

  • end 的值不包含在结果中,这一点容易出错。
  • 负数步长(如 [::-1])可实现数组反转。

多维数组的索引与切片

多维数组的索引逻辑

多维数组的索引通过逗号分隔多个维度的索引。例如,二维数组的 arr[row, column] 表示行和列的位置。

示例代码

arr_2d = np.array([[1, 2, 3],  
                  [4, 5, 6],  
                  [7, 8, 9]])  

print(arr_2d[1, 2])  # 输出6  

print(arr_2d[-1, 0])  # 输出7  

比喻:将二维数组想象为表格,row 是行数,column 是列数,类似 Excel 的单元格定位。


切片多维数组的技巧

多维切片需要为每个维度指定范围。例如,arr[start_row:end_row, start_col:end_col] 可提取子矩阵。

示例代码

sub_arr = arr_2d[:2, :2]  
print(sub_arr)  

third_col = arr_2d[:, 2]  
print(third_col)  # 输出 [3 6 9]  

关键点

  • 省略 startend 表示取该维度的所有元素。
  • 通过 : 可保持某一维度的完整性,例如 arr[:, 1] 提取某一列。

高级索引与切片技巧

布尔索引:基于条件筛选数据

布尔索引允许通过条件表达式(如 arr > 5)筛选满足条件的元素。

示例代码

mask = arr > 5  
filtered = arr[mask]  
print(filtered)  # 输出 [10 20 30 40 50]  

print(arr[arr > 25])  # 输出 [30 40 50]  

比喻:如同用滤网过滤水中的杂质,布尔索引用条件作为“滤网”,筛选出符合条件的元素。


花式索引:非连续元素的选择

花式索引(Fancy Indexing)允许通过整数列表直接选取多个非连续的元素或子数组。

示例代码

indices = [0, 2, 4]  
selected = arr[indices]  
print(selected)  # 输出 [10 30 50]  

rows = [0, 2]  
cols = [1, 2]  
print(arr_2d[rows, cols])  

注意:花式索引的结果会“压平”维度,即 arr_2d[[0,2], [1,2]] 返回一维数组。


视图与副本:切片的副作用

当对数组进行切片时,默认返回的是原数组的“视图”(View),而非独立副本。这意味着对视图的修改会影响原数组。

示例代码

slice_view = arr[:3]  
slice_view[0] = 100  
print(arr)  # 输出 [100 20 30 40 50]  

slice_copy = arr[:3].copy()  
slice_copy[0] = 200  
print(arr)  # 原数组不变,仍为 [100 20 30 40 50]  

比喻:视图就像一面镜子,映射原数组的内容,而副本则是完全独立的“克隆体”。


实战案例:切片与索引的应用场景

案例1:图像数据的裁剪与缩放

假设有一个 512x512 的图像数组,需提取中心 256x256 的区域并缩小为 128x128:

image = np.random.rand(512, 512)  
center_crop = image[128:384, 128:384]  # 中心区域  
smaller_image = center_crop[::2, ::2]  # 步长2实现缩小  

案例2:时间序列数据的筛选与统计

处理温度数据,筛选出某日温度超过 30°C 的时段,并计算平均值:

temps = np.array([28, 31, 33, 29, 34, 30, 27])  
hot_days = temps[temps > 30]  
avg_temp = hot_days.mean()  
print(f"高温平均温度:{avg_temp:.1f}°C")  # 输出:32.5°C  

结论

通过本文的讲解,读者应已掌握 NumPy 切片和索引 的核心逻辑与高级技巧。从基础的索引定位到多维切片,再到布尔索引与花式索引,这些工具能显著提升数据处理的效率与灵活性。在实际开发中,理解视图与副本的区别尤为重要,避免因意外修改数据引发的逻辑错误。

建议读者通过以下方式巩固知识:

  1. 使用 Jupyter Notebook 进行交互式练习,尝试不同切片组合。
  2. 针对真实数据集(如 CSV 文件或图像数据)设计切片任务。
  3. 参考 NumPy 官方文档,探索 np.where()np.take() 等进阶函数。

掌握 NumPy 切片和索引 后,开发者将能更自信地处理复杂的数据结构,为后续学习 Pandas、深度学习框架(如 TensorFlow)打下坚实基础。

最新发布