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

机器学习与深度学习的 Python 基础之 NumPy(2)

第二章 数组索引

导读

  • 本章重点回答三个问题:
    • 如何正确访问与修改数组中元素(含一维/二维多维)?
    • 切片得到的是“视图”还是“拷贝”?如何避免隐式联动修改?
    • 花式索引的适用场景与规则是什么?

一、基本元素访问

  • 一维数组:
    • 正向索引从 0 开始,负向索引从 -1 表示最后一个。
    • 访问并修改均支持索引位置,例如 arr[3] = 100
  • 二维数组:
    • 使用 arr[row, col],先行后列;负索引同样有效(如 -1 表示最后一行/列)。
    • 数组元素的类型可能触发类型提升(如把整型数组某元素赋为浮点数)。

示例:

arr1 = np.arange(1, 10)
arr1[3] = 100   # 就地修改
arr2 = np.array([[1,2,3],[4,5,6]])
val = arr2[0,2]  # 第1行第3列

要点:

  • 推荐一次性使用 arr[row, col] 而不是 arr[row][col],后者会产生中间数组,不统一也更低效。

二、切片基础

  • 语法:arr[start:end:step]
    • start 省略默认 0;end 省略默认到末尾;step 省略默认 1。
    • 既支持正向区间,也支持负索引;支持步长控制。
  • 一维切片常用形态:
    • arr[1:4]arr[1:]arr[:4]arr[::2]arr[1:-1:2] 等。
  • 二维切片:arr[row_slice, col_slice]
    • arr[1] 取第二行(一维视图)。
    • arr[1:3, 1:-1] 取第2-3行与第2-倒数第2列子矩阵。
    • arr[::3, ::2] 跨步采样行列。
    • arr[:,2] 第3列(一维视图),arr[:,1:3] 第2-3列(二维视图)。

示例:

arr2 = np.arange(1, 21).reshape(4, 5)
row = arr2[2, :]       # 第3行
block = arr2[1:3, 2:4] # 子矩阵
col = arr2[:, 2]       # 第3列(一维)

实用技巧:

  • 取出列后可 reshape/转置以满足后续计算接口需求:
col = arr2[:, 2]         # shape: (4,)
col_row = col.reshape(1, -1)  # shape: (1, 4)
col_col = col_row.T           # shape: (4, 1)

三、切片是视图

  • NumPy 的“切片”默认返回视图(view),与原数组共享同一底层数据。
  • 对切片做原地修改,会反映到原数组。

示例:

arr = np.arange(10)
cut = arr[:3]   # 视图
cut[0] = 100
# arr[0] 也会变为 100

如何避免联动修改?

  • 显式使用 copy() 获取独立副本:
copy = arr[:3].copy()
copy[0] = 200  # arr 不受影响

四、变量赋值“仅是绑定”

  • arr2 = arr1 不会复制数据,只是让两个变量指向同一块内存(同一底层数组)。
  • 修改任意一方,另一方“看见”的也是被修改的数据。

示例:

arr1 = np.arange(10)
arr2 = arr1     # 引用同一底层数据
arr2[0] = 100
# arr1[0] 也会变为 100

避免“误共享”的两种常见方式:

  • 使用 arr.copy() 创建深拷贝。
  • 或基于切片后再 .copy(),在管道式处理时更明确。

五、花式索引

  • 定义:使用“整数数组或列表作为索引”,一次选择多个位置。
  • 本质:返回新数组(副本),不是视图。
  • 一维花式索引:
arr = np.arange(0, 90, 10)
picked = arr[[0, 2, 5]]  # 下标0、2、5处的元素
  • 二维花式索引的“配对取值”:
    • arr[[r1, r2, ...], [c1, c2, ...]] 会取出 (r1,c1),(r2,c2),... 这些坐标对应的元素。
arr2 = np.arange(1, 17).reshape(4, 4)
vals = arr2[[0,1,2],[2,1,0]]  # 依次取 (0,2),(1,1),(2,0)
  • 花式索引也常用于“定点批量赋值”:
arr2[[0,1,2,3],[3,2,1,0]] = 100  # 反对角线元素全部设为100

注意:

  • 花式索引与切片语法“:”不能混在同一维度的同一组整数索引列表里(不同维度可混用,如 arr[:, [1,3]])。

六、常见易错点与最佳实践

  • 易错点
    • 误以为切片是“拷贝”,实为“视图”(共享底层数据)。
    • arr2 = arr1 没有复制;需要独立数据需显式 .copy()
    • arr[row][col] 的链式取法不是最佳实践,易产生中间结果与歧义。
    • 花式索引返回副本,后续修改不会影响原数组;与切片行为不同。
  • 最佳实践
    • 二维索引推荐一次性写成 arr[row, col]
    • 需要独立数据时,务必使用 .copy()
    • 批量位置更新,用花式索引更直观;区段连续选取,用切片更高效。

七、速查表(Cheat Sheet)

  • 一维元素:arr[i]arr[-1]
  • 一维切片:arr[s:e:step],默认 s=0,e=len,step=1
  • 二维元素:arr[r, c]
  • 二维切片:arr[r_s:e, c_s:e]arr[:, c]
  • 花式索引:
    • 一维:arr[[i1, i2, ...]]
    • 二维配对:arr[[r1, r2, ...],[c1, c2, ...]]
  • 视图/拷贝:
    • 切片→视图;花式索引→拷贝;arr2=arr1→同一底层。
    • 深拷贝:arr.copy()

八、学习要点(总结)

  • 索引统一用中括号:NumPy 支持 arr[1, 2] 多维一次完成;相比 Python 原生列表更简洁。
  • 花式索引的核心是“用数组作为索引”,能一次取多个元素/不连续区域;N 维就需要提供 N 个索引数组(或列表)。
  • 花式索引与普通切片的根本区别:花式索引返回“副本”,切片返回“视图”。
  • 花式索引内不能使用 : 切片语法(同一维度),若需跨维度组合,可写成 arr[:, idx_list]
  • NumPy 的切片是“视图”,如需独立数据用 .copy()
  • NumPy 在数值索引、切片上极其强大,适合科学计算与向量化;原生 Python 列表仍适用于动态结构变更(增删元素等)。

九、NumPy 与 Python 原生 list / C 数组的对比

虽然 Python 的 list、C 语言的数组和 NumPy 的 ndarray 都可以存储数据,但它们在设计目标、性能、内存布局和索引能力上有本质区别。理解这些差异,有助于我们选择合适的工具。

1. 索引语法对比
类型访问方式示例说明
Python list链式索引lst[1][2]每层是独立对象,效率低
C 数组多维语法或指针arr[1][2]*(arr + 1*cols + 2)连续内存,高效
NumPy ndarray直接多维索引arr[1, 2]一步到位,高效且清晰

🔺 优势:NumPy 的 arr[i,j]listlst[i][j] 更高效,语法更简洁。


2. 切片能力对比
类型支持多维切片?切片返回说明
Python list❌ 仅支持一维切片✅ 副本lst[1:3] 可,lst[1:3, 2:4] 报错
C 数组❌ 不支持切片语法❌ 无切片概念需手动循环复制
NumPy ndarray✅ 支持多维切片视图(默认)arr[1:3, 2:4] 返回子矩阵视图

🔺 优势:NumPy 的切片是科学计算的利器,支持多维、跨步、布尔索引等高级操作。


3. 内存与性能对比
类型内存布局数据类型性能
list指针数组(不连续)任意对象(异构)慢(缓存不友好)
C 数组连续内存固定类型(同构)快(缓存友好)
NumPy ndarray连续内存(C/F-order)固定类型(同构)极快(向量化)

🔺 NumPy 本质是“Python 接口 + C 性能”,既易用又高效。


4. 动态性对比
类型支持动态增删?适用场景
list✅ 支持 append, pop, insert动态结构、通用容器
C 数组❌ 固定大小嵌入式、性能敏感
NumPy ndarray❌ 固定大小(需 .copy() 扩展)数值计算、矩阵运算

结论

  • NumPy科学计算、数据分析、机器学习
  • list动态结构、流程控制、通用数据容器

5. 花式索引 vs 普通索引
能力Python listNumPy ndarray
不连续索引[lst[i] for i in [0,2,5]]arr[[0,2,5]]
布尔索引手动循环或推导式arr[arr > 5]
广播与向量化❌ 不支持✅ 支持

🔺 NumPy 的花式索引是向量化编程的核心,极大提升代码简洁性与性能。


✅ 总结:工具选择建议
需求推荐工具
数值计算、矩阵运算、图像处理NumPy
动态添加/删除元素、通用容器Python list
嵌入式、极致性能、C/C++ 集成C 数组

🎯 一句话

  • NumPy 强在“数值+多维+向量化”
  • list 强在“动态+通用+灵活”
  • 二者互补,而非替代


http://www.xdnf.cn/news/19776.html

相关文章:

  • uniapp+vue3 微信小程序全屏广告组件功能
  • AI IDE+AI 辅助编程,真能让程序员 “告别 996” 吗?
  • 【LeetCode_283】移动零
  • 技术小白如何快速的了解opentenbase?--把握四大特色
  • XE 旧版本 JSON 处理
  • 使用 Uni-app 打包 外链地址APK 及 iOS 注意事项
  • K8S-基础架构
  • 离开职场2个月,后知后觉的反思。
  • 素材合集!直播间带货音乐BGM合集,抖音直播间常用热门音乐合集,根据中文分类,方便查找
  • 力扣hot100:矩阵置零(73)(原地算法)
  • 【Python语法基础学习笔记】类的定义和使用
  • WSL + VSCode + Git + Node.js 开发环境配置文档
  • python数据分析 与spark、hive数据分析对比
  • 使用pyspark对上百亿行的hive表生成稀疏向量
  • 2025年COR IOTJ SCI2区,灾后通信无人机基站位置优化和移动充电无人机路径规划,深度解析+性能实测
  • Android aoap开发常见问题之package_allowed_list.txt导致的编译报错
  • 深度学习------模型的保存和使用
  • 深度学习篇---Adam优化器
  • Docker Pull 代理配置方法
  • 【正则表达式】 正则表达式有哪些语法?
  • Low-Light Image Enhancement via Structure Modeling and Guidance 论文阅读
  • AP5414:高效灵活的LED驱动解决方案,点亮创意生活
  • go大厂真实的面试经历与总结
  • 心路历程-初识Linux用户
  • EasyExcel 基础用法
  • 如何在FastAPI中巧妙隔离依赖项,让单元测试不再头疼?
  • 一文吃透 `protoc` 安装与落地
  • 【Spring Cloud微服务】10.王子、巨龙与Spring Cloud:用注解重塑微服务王国
  • 普通人也能走的自由之路
  • 科技赋能田园:数字化解决方案开启智慧农业新篇章