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

第二章 数组索引

导读

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

一、基本元素访问

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

示例:

python 复制代码
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列(二维视图)。

示例:

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

实用技巧:

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

三、切片是视图

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

示例:

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

如何避免联动修改?

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

四、变量赋值"仅是绑定"

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

示例:

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

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

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

五、花式索引

  • 定义:使用"整数数组或列表作为索引",一次选择多个位置。
  • 本质:返回新数组(副本),不是视图。
  • 一维花式索引:
python 复制代码
arr = np.arange(0, 90, 10)
picked = arr[[0, 2, 5]]  # 下标0、2、5处的元素
  • 二维花式索引的"配对取值":
    • arr[[r1, r2, ...], [c1, c2, ...]] 会取出 (r1,c1),(r2,c2),... 这些坐标对应的元素。
python 复制代码
arr2 = np.arange(1, 17).reshape(4, 4)
vals = arr2[[0,1,2],[2,1,0]]  # 依次取 (0,2),(1,1),(2,0)
  • 花式索引也常用于"定点批量赋值":
python 复制代码
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 list NumPy 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 强在"动态+通用+灵活"
  • 二者互补,而非替代


相关推荐
Ronin-Lotus2 小时前
深度学习篇---SGD+Momentum优化器
人工智能·深度学习·机器学习
Cold_Rain023 小时前
利用 Python 绘制环形热力图
python·数学建模·数据可视化
在钱塘江3 小时前
LangGraph从新手到老师傅 - 3 - StateGraph基础入门
人工智能·python
Go_Zezhou3 小时前
在线性代数里聊聊word embedding
线性代数·算法·机器学习·nlp
感哥3 小时前
Django用户认证权限
python·django
思辨共悟3 小时前
python数据分析 与spark、hive数据分析对比
python·数据分析·spark
Christo33 小时前
TFS-2005《A Possibilistic Fuzzy c-Means Clustering Algorithm》
人工智能·算法·机器学习
aiden:)3 小时前
Selenium WebUI 自动化“避坑”指南——从常用 API 到 10 大高频问题
开发语言·前端·javascript·python·selenium
Lenskit3 小时前
使用pyspark对上百亿行的hive表生成稀疏向量
python·spark-ml·spark