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

NumPy 系列(三):numpy 数组的索引

前面我们规定,将一维数组称为向量,将二维数组称为矩阵。

3.1 访问数组元素

与 Python 列表一致,访问 NumPy 数组元素时使用中括号,索引由 0 开始。

(1)访问向量

import numpy as np
# 创建向量
arr1=np.arange(1,10)
print(arr1)
[1 2 3 4 5 6 7 8 9]
print(arr1[3])
print(arr1[-1])
4
9
arr1[3]=100
print(arr1)
[  1   2   3 100   5   6   7   8   9]

(2) 访问矩阵

arr2=np.array([[1,2,3],[4,5,6]])
print(arr2)
[[1 2 3][4 5 6]]
print(arr2[0,2])
print(arr2[1,-2])
3
5
arr2[1,1]=100.9
print(arr2)
[[  1   2   3][  4 100   6]]

在 In [7]中,浮点数 100.9 插入到整数型数组时被截断了。

3.2 花式索引

花式索引(Fancy indexing)又名“花哨的索引”,UP 认为不应该用“花哨”
来形容,这里的 Fancy 应取“华丽的、巧妙的、奢华的、时髦的”之义。

上一小节访问单个元素时,向量用 arr1[x],矩阵用 arr2[x,y]。逗号在矩阵里
用于区分行与列,这一小节,逗号新增一个功能,且不会与矩阵里的逗号混淆。
普通索引用一层中括号,花式索引用两层中括号。

(1)向量的花式索引

import numpy as np
arr1=np.arange(0,90,10)
print(arr1)
print(arr1[[0,2]])
[ 0 10 20 30 40 50 60 70 80]
[ 0 20]

(2)矩阵的花式索引

import numpy as np
arr2=np.arange(12).reshape(3,4)
print(arr2)
print(arr2[[0,2],[2,1]])
print(arr2[[1,0,2],[1,1,2]])
arr2[[1,0,2],[1,1,2]]=100
print(arr2)
[[ 0  1  2  3][ 4  5  6  7][ 8  9 10 11]]
[2 9]
[ 5  1 10]
[[  0 100   2   3][  4 100   6   7][  8   9 100  11]]

根据以上实例,花式索引输出的仍然是一个向量。

要在 Markdown 中打出这个表格,可按照以下格式编写:

索引方式向量矩阵
普通索引arr1[x,]arr2[x, y]
花式索引arr1[[x₁,x₂,…,xₙ],]arr2[[x₁,x₂,…,xₙ], [y₁,y₂,…,yₙ]]

3.3 访问数组切片

(1)向量的切片

向量与列表切片的操作完全一致,因此本页内容在 Python 基础中均有涉及。

import numpy as np
arr1=np.arange(10)
print(arr1)
print(arr1[1:4])
print(arr1[2:])
print(arr1[:4])
[0 1 2 3 4 5 6 7 8 9]
[1 2 3]
[2 3 4 5 6 7 8 9]
[0 1 2 3]
print(arr1)
print(arr1[2:-2]) # 舍去首尾2个
print(arr1[2:]) # 舍去头2个
print(arr1[:-2]) # 舍去尾部2个
[0 1 2 3 4 5 6 7 8 9]
[2 3 4 5 6 7]
[2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7]
print(arr1)
print(arr1[::2])
print(arr1[::3])
print(arr1[1:-1:2])
[0 1 2 3 4 5 6 7 8 9]
[0 2 4 6 8]
[0 3 6 9]
[1 3 5 7]

(2) 矩阵的切片

import numpy as np
arr2=np.arange(24).reshape(4,6)
print(arr2)
print(arr2[1:3,2:4])
print(arr2[::2,::3])
[[ 0  1  2  3  4  5][ 6  7  8  9 10 11][12 13 14 15 16 17][18 19 20 21 22 23]]
[[ 8  9][14 15]]
[[ 0  3][12 15]]

(3)提取矩阵的行

基于矩阵的切片功能,我们可以提取其部分行,如示例所示。

import numpy as np
arr3=np.arange(1,21).reshape(4,5)
print(arr3)
print(arr3[1:3,:])
[[ 1  2  3  4  5][ 6  7  8  9 10][11 12 13 14 15][16 17 18 19 20]]
[[ 6  7  8  9 10][11 12 13 14 15]]

考虑代码的简洁,当提取矩阵的某几行时可简写(但提取列的时候不可简写)。

print(arr3[2,:]) # 规范提取行
print(arr3[2]) # 简便提取行
[11 12 13 14 15]
[11 12 13 14 15]

所以,有时你可能看到诸如 arr[1][2] 这样的语法,不必吃惊,其实这只是先
提取了第 1 行,再提取该行中第 2 个元素。提一句,UP 并不推荐这样的写法。

(4)提取矩阵的列

基于矩阵的切片功能,我们可以提取其部分列,如示例所示。

import numpy as np
arr4=np.arange(1,21).reshape(4,5)
print(arr4)
print(arr4[:,1]) # 提取第2列(注意:输出的是向量!!)
print(arr4[:,2:-1])
[[ 1  2  3  4  5][ 6  7  8  9 10][11 12 13 14 15][16 17 18 19 20]]
[ 2  7 12 17]
[[ 3  4][ 8  9][13 14][18 19]]

值得注意的是,提取某一个单独的列时,出来的结果是一个向量。其实这么
做只是为了省空间,我们知道,列矩阵必须用两层中括号来存储,而形状为 1000
的向量,自然比形状为(1000,1)的列矩阵更省空间(节约了 1000 对括号)。

import numpy as np
arr5=np.arange(1,16).reshape(3,5)
print(arr5)
print(arr5[:,4])
# print(arr5[:,4].T) 向量无法转置,所以要先变成矩阵
arr6=arr5.reshape(-1,1)
print(arr6)
arr7=arr5.reshape(1,-1).T
print(arr7)
[[ 1  2  3  4  5][ 6  7  8  9 10][11 12 13 14 15]]
[ 5 10 15]
[[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12][13][14][15]]
[[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12][13][14][15]]

3.4 数组切片仅是视图

(1)数组切片仅是视图

与 Python 列表和 Matlab 不同,NumPy 数组的切片仅仅是原数组的一个视
图。换言之,NumPy 切片并不会创建新的变量,示例如下。

import numpy as np
arr=np.arange(10)
print(10)
arr1=arr[1:5]
arr1[2]=100 # 对切片进行修改
print(arr) # 原数组也会被更改
10
[  0   1   2 100   4   5   6   7   8   9]

习惯 Matlab 的用户可能无法理解,但其实这正是 NumPy 的精妙之处。试想
一下,一个几百万条数据的数组,每次切片时都创建一个新变量,势必造成大量
的内存浪费。因此,NumPy 的切片被设计为原数组的视图是极好的。
深度学习中为节省内存,将多次使用 arr[:] = <表达式> 来替代 arr = <表达式>。

(2)备份切片为新变量

如果真的需要为切片创建新变量(这种情况很稀少),使用 .copy() 方法。

import numpy as np
arr=np.arange(10)
print(arr)
copy=arr[:4].copy() # 创建切片的副本
copy[2]=100
print(arr) # 原数组不变
print(copy)
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[  0   1 100   3]

3.5 数组赋值仅是绑定

(1)数组赋值仅是绑定

与 NumPy 数组的切片一样,NumPy 数组完整的赋值给另一个数组,也只是
绑定。换言之,NumPy 数组之间的赋值并不会创建新的变量,示例如下。

import numpy as np
arr1=np.arange(10)
print(arr1)
arr2=arr1
arr2[2]=100
print(arr2)
print(arr1) # 原数组也被改变
[0 1 2 3 4 5 6 7 8 9]
[  0   1 100   3   4   5   6   7   8   9]
[  0   1 100   3   4   5   6   7   8   9]

此特性的出现仍然是为了节约空间,破局的方法仍然与前面相同。

(2)复制数组为新变量

如果真的需要赋给一个新数组,使用 .copy() 方法。

import numpy as np
arr1=np.arange(10)
print(arr1)arr2=arr1.copy()
print(arr2)arr2[2]=200
print(arr1)
print(arr2)
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[  0   1 200   3   4   5   6   7   8   9]
http://www.dtcms.com/a/393477.html

相关文章:

  • STL源码探秘(一):深入剖析List的迭代器设计与实现
  • PNP机器人九月具身智能引领FRANKA机器人具身智能技术创新与人形机器人产业全球化新格局,全球具身领先生态推动模型部署和泛化
  • ACP(八):用插件扩展答疑机器人的能力边界
  • 迁移学习:从理论到实践,让模型 “举一反三” 的核心技术
  • ACP(六)自动化评测机器人的表现
  • 【MySQL数据库】MySQL的第一步:从安装启动到用户权限配置的一站式实战指南
  • MySQL笔记7
  • 【C语言】C语言预处理详解,从基础到进阶的全面讲解
  • Spotify:递归嵌入与聚类(四)
  • 三种查询语言比较:SQL、SPL、PromQL
  • [Windows] 迅连科技音频处理工具 CyberLink AudioDirector 2026 16.0.5703.0 中文多语免费版
  • (一)React面试(虚拟DOM/类组件)
  • 亲历 2025 机器人大赛:科技碰撞的震撼与启迪
  • Chromium 138 编译指南 Ubuntu篇:Python环境与开发工具配置(五)
  • 在CentOS上配置SVN至Web目录的自动同步
  • 一款不错的PDF工具,吾爱出品
  • Sleuth + Zipkin:微服务监控之分布式链路追踪技术
  • JVM 调优在分布式场景下的特殊策略:从集群 GC 分析到 OOM 排查实战(一)
  • 【开题答辩全过程】以 基于Vue技术实现权限管理系统为例,包含答辩的问题和答案
  • Redis 高可用架构全解析:主从复制、哨兵与集群模式
  • Redis全面解析:从基础配置到高可用集群
  • Redis:高性能Key-Value存储与缓存利器
  • Redis 三种核心服务架构详解:主从复制、哨兵模式与集群模式
  • Redis 三种服务架构详解:主从复制、哨兵模式与集群
  • 速通ACM省铜第十一天 赋源码(Gellyfish and Flaming Peony)
  • JAVA八股文——JAVA堆
  • Spark专题-第二部分:Spark SQL 入门(7)-算子介绍-Windows
  • JavaScript 闭包(Closure)深度讲解
  • QT与Spring Boot通信:实现HTTP请求的完整指南
  • 服务器ubuntu 22.04装nvidia驱动