Python基础——NumPy学习

引言

这里由于后续入门强化学习,涉及到数据处理相关,需要学习 numpyPandas 库,这里主要参考了该网站学习资料撰写学习笔记,主要目的是熟悉操作,后续使用时候方便查找。


1 NumPy Ndarray 对象

1.1 基本介绍

  1. NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。
  2. ndarray 对象是用于存放同类型元素的多维数组。
  3. ndarray 中的每个元素在内存中都有相同存储大小的区域。
  4. ndarray 内部由以下内容组成:
    1. 一个指向数据(内存或内存映射文件中的一块数据)的指针。
    2. 数据类型或 dtype,描述在数组中每个元素的类型。
    3. 一个表示数组形状(shape)的元组,表示各维度大小的元组。
    4. 一个跨度元组(stride),表示在内存中从当前元素指向同一数组中下一元素的字节间隔。
  5. ndarray 的内部结构:

跨度可以是负数,这样会使数组在内存中后向移动,切片中 obj[::-1] 或 obj[:,::-1] 就是如此。

  1. 创建一个 ndarray 只需调用 NumPy 的 array 函数即可:
1
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
  1. 参数说明
名称 描述
object 数组或嵌套的数列
dtype 数组元素的数据类型,可选
copy 对象是否需要复制,可选
order 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)
subok 默认返回一个与基类类型一致的数组
ndmin 指定生成数组的最小维度

1.2 实例

接下来可以通过以下实例帮助我们更好的理解。

  1. 实例1
1
2
3
import numpy as np
a = np.array([1, 2, 3])
print(a)

  1. 实例2
1
2
3
4
# 多于一个维度  
import numpy as np
a = np.array([[1, 2], [3, 4]])
print (a)

  1. 实例3
1
2
3
4
# 最小维度  
import numpy as np
a = np.array([1, 2, 3], ndmin=2)
print(a, np.shape(a))

  1. 实例4
1
2
3
4
# dtype 参数  
import numpy as np
a = np.array([1, 2, 3], dtype = complex)
print(a)

ndarray 对象由计算机内存的连续一维部分组成,并结合索引模式,将每个元素映射到内存块中的一个位置。内存块以行顺序(C样式)或列顺序(FORTRAN或MatLab风格,即前述的F样式)来保存元素。


2 NumPy 数据类型

numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和 C 语言的数据类型对应上,其中部分类型对应为 Python 内置的类型。

下表列举了常用的 NumPy 数据类型:

名称 描述
bool_ 布尔型数据类型(True 或者 False)
int_ 默认的整数类型(类似于 C 语言中的 long,int32 或 int64)
intc 与 C 的 int 类型一样,一般是 int32 或 int64
intp 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)
int8 字节(-128 to 127)
int16 整数(-32768 to 32767)
int32 整数(-2147483648 to 2147483647)
int64 整数(-9223372036854775808 to 9223372036854775807)
uint8 无符号整数(0 to 255)
uint16 无符号整数(0 to 65535)
uint32 无符号整数(0 to 4294967295)
uint64 无符号整数(0 to 18446744073709551615)
float_ float64 类型的简写
float16 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_ complex128 类型的简写,即 128 位复数
complex64 复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128 复数,表示双 64 位浮点数(实数部分和虚数部分)

numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,包括 np.bool_np.int32np.float32,等等。

2.1 数据类型对象 (dtype)

  1. 数据类型对象(numpy.dtype 类的实例)用来描述与数组对应的内存区域是如何使用的,他描述了数据的以下几个方面:
    1. 数据的类型(整数,浮点数或者Python对象)
    2. 数据的大小(例如,整数使用多少字节存储)
    3. 数据的字节顺序(小端法或大端法)
    4. 在结构化类型的情况下,字段的名称、每个字段的数据类型和每个字段所取的内存块的部分
    5. 如果数据类型是子数组,那么它的形状和数据类型是什么。
  2. 字节顺序是通过对数据类型预先设定<>来实现的。
    1. < 表示小端法(低位地址存放低地址字节,高位地址存放高地址字节)
    2. > 表示大端法(低位地址存放高地址字节,高位地址存放低地址字节)
  3. dtype 对象是使用以下语法构造的:
1
numpy.dtype(object, align, copy)
  • object:数据类型的对象
  • align:如果为 True,则为结构化数据类型创建一个对齐的字段,填充字段使其类似 C 的结构体
  • copy:如果为 True,则创建一个 dtype 对象的新副本,否则返回 dtype 对象的引用

2.2 实例

  1. 实例1
1
2
3
4
import numpy as np
# 使用标量类型
dt = np.dtype(np.int32)
print(dt)

  1. 实例2
1
2
3
4
import numpy as np
# int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替
dt = np.dtype('i4')
print(dt)

  1. 实例3
1
2
3
4
import numpy as np
# 字节顺序标注
dt = np.dtype('<i4')
print(dt)
  • 这里<i4表示小端法,即低地址存放低地址字节,高地址存放高地址字节。
  1. 实例4
1
2
3
4
5
6
7
8
9
10
11
import numpy as np

# 定义结构化数据类型
dt = np.dtype([('age', np.int8)])

# 创建使用该类型的数组
arr = np.array([(25,), (30,), (18,)], dtype=dt)

# 访问数组中的字段
print(arr['age']) # 输出:[25 30 18](直接获取所有元素的'age'字段)
print(arr[0]['age']) # 输出:25(获取第一个元素的'age'字段)

  • 参数 [('age', np.int8)]
    • 这是一个列表,每个元素是一个元组,代表结构化类型中的一个 “字段”。
    • 元组 ('age', np.int8) 中:
      • 第一个元素 'age' 是字段名称(类似字典的键),用于标识该字段。
      • 第二个元素 np.int8 是字段的数据类型,表示该字段存储 8 位整数(范围:-128 到 127)。
  1. 实例5

下面的示例定义一个结构化数据类型 student,包含字符串字段 name,整数字段 age,及浮点字段 marks,并将这个 dtype 应用到 ndarray 对象。

1
2
3
4
5
6
7
8
import numpy as np
student = np.dtype([('name', 'S20'), ('age', 'i1'), ('mark', 'f4')])
print(student)
a = np.array([('zhangsan', 20, 80), ('lisi', 21, 85)], dtype=student)
print(a)
print(a['name'])
print(a['age'])
print(a['mark'])

2.3 内建类型

  • 每个内建类型都有一个唯一定义它的字符代码,如下:
字符 对应类型
b 布尔型
i (有符号) 整型
u 无符号整型 integer
f 浮点型
c 复数浮点型
m timedelta(时间间隔)
M datetime(日期时间)
O (Python) 对象
S, a (byte-)字符串
U Unicode
V 原始数据 (void)

3 NumPy 数组类型

  1. NumPy 数组的维数称为秩(rank),秩就是轴的数量,即数组的维度,一维数组的秩为1, 二维数组的秩为2,以此类推。
  2. 在 NumPy 中,每一个线性的数组称为一个轴(axis),也就是维度(dimension)。比如说,二维数组就相当于两个一维数组,其中第一个一维数组中每一个元素有相当于一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维度。
  3. 很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。
  4. NumPy 的数组中比较重要 ndarray 对象属性有:
属性 说明
ndarray.ndim 数组的秩(rank),即数组的维度数量或轴的数量。
ndarray.shape 数组的维度,表示数组在每个轴上的大小。对于二维数组(矩阵),表示其行数和列数。
ndarray.size 数组中元素的总个数,等于 ndarray.shape 中各个轴上大小的乘积。
ndarray.dtype 数组中元素的数据类型。
ndarray.itemsize 数组中每个元素的大小,以字节为单位。
ndarray.flags 包含有关内存布局的信息,如是否为 C 或 Fortran 连续存储,是否为只读等。
ndarray.real 数组中每个元素的实部(如果元素类型为复数)。
ndarray.imag 数组中每个元素的虚部(如果元素类型为复数)。
ndarray.data 实际存储数组元素的缓冲区,一般通过索引访问元素,不直接使用该属性。

3.1 ndarray.ndim

  • ndarray.ndim 用于获取数组的维度数量(即数组的轴数)。
1
2
3
4
5
6
7
import numpy as np

a = np.arange(24)
print(a.ndim)
# 现在调整其大小
b = a.reshape(2,4,3)
print(b.ndim)

3.2 ndarray.shape

  • ndarray.shape 表示数组的维度,返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性(秩)。比如,一个二维数组,其维度表示"行数"和"列数"。
  • ndarray.shape 也可以用于调整数组大小。
1
2
3
4
5
6
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
a.shape = (3, 2)
print(a)

  • NumPy 也提供了 reshape 函数来调整数组大小。
1
2
3
4
5
import numpy as np 

a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape(3, 2)
print(b)

ndarray.reshape 通常返回的是非拷贝副本,即改变返回后数组的元素,原数组对应元素的值也会改变。

1
2
3
4
5
6
7
8
9
import numpy as np 

a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape(3, 2)
print(b)
b[0][0] = 100
print("---------------------")
print(b)
print(a)

3.3 ndarray.itemsize

  • ndarray.itemsize 以字节的形式返回数组中每一个元素的大小
  • 例如,一个元素类型为 float64 的数组 itemsize 属性值为 8(float64 占用 64 个 bits,每个字节长度为 8,所以 64/8,占用 8 个字节),又如,一个元素类型为 complex32 的数组 item 属性为 4(32/8)。
1
2
3
4
5
6
7
8
9
import numpy as np

# 数组的 dtype 为 int8(一个字节)
x = np.array([1, 2, 3, 4, 5], dtype=np.int8)
print(x.itemsize)

# 数组的 dtype 现在为 float64(八个字节)
y = np.array([1, 2, 3, 4, 5], dtype=np.float64)
print(y.itemsize)

3.4 ndarray.flags

  • ndarray.flags 提供了关于数组内存布局的信息,返回一个包含布尔值的对象,用于描述数组的内存布局。
属性 描述
C_CONTIGUOUS © 数据是在一个单一的C风格的连续段中
F_CONTIGUOUS (F) 数据是在一个单一的Fortran风格的连续段中
OWNDATA (O) 数组拥有它所使用的内存或从另一个对象中借用它
WRITEABLE (W) 数据区域可以被写入,将该值设置为 False,则数据为只读
ALIGNED (A) 数据和所有元素都适当地对齐到硬件上
UPDATEIFCOPY (U) 这个数组是其它数组的一个副本,当这个数组被释放时,原数组的内容将被更新
1
2
3
4
import numpy as np 

x = np.array([1,2,3,4,5])
print (x.flags)

虽然把 a.flags.writeable 改为了 False(只读),但是在数组 b 上的操作仍然会影响数组 a,因为数组 a 和数组 b 共享底层的数据缓冲区。这是由于 reshape 操作不会创建新的数据副本,而是使用相同的数据,只是以新的形状进行解释。

1
2
3
4
5
6
7
8
9
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape((3, 2))
print(b)
a.flags.writeable = False
b[0][0] = 666
print(b)
print(a)
print(a.flags)


4 NumPy 创建数组

ndarray 数组除了可以使用底层 ndarray 构造器来创建外,也可以通过以下几种方式来创建。

4.1 numpy.empty

  • numpy.empty 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组:
1
numpy.empty(shape, dtype = float, order = 'C')
  • 参数说明
参数 描述
shape 数组形状
dtype 数据类型,可选
order 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
  • 实例
1
2
3
import numpy as np
x = np.empty((3, 2), dtype=int)
print(x)

注意:这里数组元素为随机值,因为它们未初始化。

4.2 numpy.zeros

  • 创建指定大小的数组,数组元素以0来填充:
1
numpy.zeros(shape, dtype = float, order = 'C')
  • 参数说明
参数 描述
shape 数组形状
dtype 数据类型,可选
order 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
  • 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np

# 默认为浮点数
x = np.zeros(5)
print(x)

# 设置类型为整数
y = np.zeros((5, ), dtype=int)
print(y)

# 自定义类型
dt = np.dtype([('x', 'i4'), ('y', 'i4')])
z = np.zeros((3, 2), dtype=dt)
print(z)

4.3 numpy.ones

  • 创建指定大小的数组,数组元素以1来填充:
1
numpy.ones(shape, dtype = None, order = 'C')
  • 参数说明
参数 描述
shape 数组形状
dtype 数据类型,可选
order 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
  • 实例
1
2
3
4
5
6
7
8
9
import numpy as np

# 默认为浮点数
x = np.ones(5)
print(x)

# 自定义类型
x = np.ones([2,2], dtype = int)
print(x)

4.4 numpy.zeros_like

  • numpy.zeros_like 用于创建一个与给定数组具有相同形状的数组,数组元素用 0 填充;
  • numpy.zeros_likenumpy.zeros 的都是用于创建一个指定形状的数组,其中元素都是 0;它们之间的区别在于:
    • numpy.zeros 可以直接指定要创建的数组的形状;
    • numpy.zeros_like 是创建一个与给定数组具有相同形状的数组。
1
numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)
  • 参数说明
参数 描述
a 给定要创建相同形状的数组
dtype 数据类型,可选
order 数组在内存中的存储顺序,可选值为 ‘C’(按行优先)或 ‘F’(按列优先),默认为 ‘K’(保留输入数组的存储顺序)
subok 是否允许返回子类,如果为 True,则返回一个子类对象,否则返回一个与 a 数组具有相同数据类型和存储顺序的数组
shape 创建的数组的形状,如果不指定,则默认为 a 数组的形状
  • 实例
1
2
3
4
5
6
7
8
import numpy as np

# 创建一个 3x3 的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 创建一个与 arr 形状相同的,所有元素都为 0 的数组
zeros_arr = np.zeros_like(arr)
print(zeros_arr)

4.5 numpy.ones_like

  • numpy.ones_like 用于创建一个与给定数组具有相同形状的数组,数组元素用 1 填充;
  • numpy.ones_likenumpy.ones 的都是用于创建一个指定形状的数组,其中元素都是 1;它们之间的区别在于:
    • numpy.ones 可以直接指定要创建的数组的形状;
    • numpy.ones_like 是创建一个与给定数组具有相同形状的数组。
1
numpy.ones_like(a, dtype=None, order='K', subok=True, shape=None)
  • 参数说明
参数 描述
a 给定要创建相同形状的数组
dtype 数据类型,可选
order 数组在内存中的存储顺序,可选值为 ‘C’(按行优先)或 ‘F’(按列优先),默认为 ‘K’(保留输入数组的存储顺序)
subok 是否允许返回子类,如果为 True,则返回一个子类对象,否则返回一个与 a 数组具有相同数据类型和存储顺序的数组
shape 创建的数组的形状,如果不指定,则默认为 a 数组的形状
  • 实例
1
2
3
4
5
6
7
8
import numpy as np

# 创建一个 3x3 的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 创建一个与 arr 形状相同的,所有元素都为 1 的数组
ones_arr = np.ones_like(arr)
print(ones_arr)


5 NumPy 从已有的数组创建数组

5.1 numpy.asarray

  • numpy.asarray 类似 numpy.array,但 numpy.asarray 的参数只有三个,比 numpy.array 少两个。
1
numpy.asarray(a, dtype = None, order = None)
  • 参数说明
参数 描述
a 任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组
dtype 数据类型,可选
order 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
  • 实例1:将列表转换为ndarray
1
2
3
4
5
import numpy as np

x = [1, 2, 3]
y = np.asarray(x)
print(y, type(y))

  • 实例2:将元组转换为ndarray
1
2
3
4
5
import numpy as np

x = (1, 2, 3)
y = np.asarray(x)
print(y, type(y))

  • 实例3:将元组列表转换为ndarray
1
2
3
4
5
6
import numpy as np

x = [(1, 2, 3), (4, 5, 6)]
y = np.asarray(x)
print(x, type(x))
print(y, type(y))

  • 实例4:设置了dtype参数
1
2
3
4
5
import numpy as np

x = [1, 2, 3]
y = np.asarray(x, float)
print(y, type(y))

5.2 numpy.frombuffer

  • numpy.buffer 用于实现动态数组。
  • numpy.buffer 接受 buffer 输入参数,以流的形式转换为 ndarray 对象。
1
numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)

注意:buffer 是字符串的时候, Python3 默认 str 是 Unicode 类型,所以要转成 bytestring 在原 str 前加上 b。

  • 参数说明
参数 描述
buffer 可以是任意对象,会以流的形式读入
dtype 返回数组的数据类型,可选
count 读取的数据数量,默认为-1,读取所有数据
offset 读取的起始位置,默认为0
  • 实例
1
2
3
4
5
import numpy as np

s = b"Hello world"
a = np.frombuffer(s, dtype='S1')
print(a)

5.3 numpy.fromiter

  • numpy.fromiter 方法从可迭代对象中建立 ndarray 对象,返回一维数组。
1
numpy.fromiter(iterable, dtype, count=-1)
  • 参数说明
参数 描述
iterable 可迭代对象
dtype 返回数组的数据类型
count 读取的数据数量,默认为-1,读取所有数据
  • 实例
1
2
3
4
5
6
7
8
9
import numpy as np

# 使用 range 函数创建列表对象
list = range(5)
it = iter(list)

# 使用迭代器创建 ndarray
x = np.fromiter(it, dtype=float)
print(x)

5.4 补充

5.4.1 Iterator 迭代器

  1. 在Python中,迭代器(Iterator)是一种可以逐个访问集合元素的对象,它能够实现对可迭代对象(如列表、元组、字典、集合等)的遍历。迭代器的核心特性是通过自身的 __next__() 方法(Python 3中)依次返回下一个元素,直到所有元素被遍历完毕后,抛出 StopIteration 异常终止迭代。
  2. 迭代器的特点
    • 惰性计算:迭代器不会一次性加载所有元素到内存,而是在调用 __next__() 时才生成下一个元素,因此适合处理大量数据或无限序列,能有效节省内存。
    • 单向遍历:迭代器只能从第一个元素开始,逐个向后访问,无法倒序或重置(若需重新遍历,需重新创建迭代器)。
    • 与可迭代对象的关系
      • 可迭代对象(Iterable)是指具有 __iter__() 方法的对象(如列表、字符串等),调用该方法会返回一个迭代器。
      • 迭代器(Iterator)本身也是可迭代对象,但它额外具有 __next__() 方法,用于获取下一个元素。
  3. 基本用法
    • 通过 iter() 函数可以将可迭代对象转换为迭代器,再通过 next() 函数(或迭代器的 __next__() 方法)获取元素。
1
2
3
4
5
6
7
8
9
10
11
# 定义一个可迭代对象(列表)
my_list = [1, 2, 3]

# 将可迭代对象转换为迭代器
my_iterator = iter(my_list)

# 逐个获取元素
print(next(my_iterator)) # 输出:1
print(next(my_iterator)) # 输出:2
print(next(my_iterator)) # 输出:3
print(next(my_iterator)) # 无元素时抛出 StopIteration 异常

5.4.2 numpy.array 与 numpy.asarray 区别

numpy.array 和 numpy.asarray 都是 NumPy 中用于将输入数据(如列表、元组、已有数组等)转换为 ndarray(NumPy 数组)的函数,但两者的核心区别在于对已有 ndarray 数据源的内存处理方式

  1. 内存行为
    • 当数据源本身已经是一个 ndarray 时,两者的行为不同:
      • numpy.array总是复制原数据,创建一个新的 ndarray 副本,新数组与原数组占用独立内存,修改原数组不会影响新数组。
      • numpy.asarray不会复制原数据,而是直接引用原 ndarray 的内存,新数组与原数组共享数据,修改原数组会同步影响新数组。
  2. 其他情况
    • 当数据源是普通 Python 对象(如列表、元组、列表的元组等)时,两者行为完全一致,都会将数据转换为新的 ndarray,且新数组是独立的副本,修改原数据源(如列表)不会影响转换后的数组。
  3. 实例1:数据源为普通列表(非 ndarray)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np

# 数据源是普通列表
data = [[1, 2, 3], [4, 5, 6]]

# 转换为 ndarray
arr1 = np.array(data)
arr2 = np.asarray(data)

# 修改原列表
data[0][0] = 100

print(arr1) # 输出:[[1 2 3], [4 5 6]](不受原列表修改影响)
print(arr2) # 输出:[[1 2 3], [4 5 6]](不受原列表修改影响)

结论:数据源为列表时,array 和 asarray 行为一致,均生成独立副本。

  1. 实例2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np

# 数据源是 ndarray
original_arr = np.array([1, 2, 3])

# 转换为新数组
arr1 = np.array(original_arr) # 复制数据
arr2 = np.asarray(original_arr) # 引用原数据

# 修改原数组
original_arr[0] = 100

print(arr1) # 输出:[1 2 3](不受原数组修改影响,因为是副本)
print(arr2) # 输出:[100 2 3](受原数组修改影响,因为是引用)

结论:数据源为 ndarray 时,array 生成独立副本,asarray 共享原数据。

  1. 应用场景
    1. 使用 numpy.array:当需要确保新数组与原数据完全独立(例如不希望原数据的修改影响新数组)时,优先使用。缺点是会额外占用内存。
    2. 使用 numpy.asarray:当可以接受新数组与原数据共享内存(例如为了节省内存,或明确需要同步修改)时,优先使用。优点是避免不必要的内存复制,效率更高。

6 NumPy 从数值范围创建数组

6.1 numpy.arange

  1. numpy 包中的使用 arange 函数创建数值范围并返回 ndarray 对象,函数格式如下:
1
numpy.arange(start, stop, step, dtype)
  1. 参数说明
参数 描述
start 起始值,默认为0
stop 终止值(不包含)
step 步长,默认为1
dtype 返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型
  1. 实例
1
2
3
4
5
import numpy as np

# 从10开始(闭区间),20结束(开区间),步长为2,生成浮点数数组
x = np.arange(10, 20, 2, float)
print(x)

6.2 numpy.linspace

  1. numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:
1
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
  1. 参数说明
参数 描述
start 序列的起始值
stop 序列的终止值,如果endpoint为true,该值包含于数列中
num 要生成的等步长的样本数量,默认为50
endpoint 该值为 true 时,数列中包含stop值,反之不包含,默认是True。
retstep 如果为 True 时,生成的数组中会显示间距,反之不显示。
dtype ndarray 的数据类型
  1. 实例1:设置起始点为 1 ,终止点为 10,数列个数为 10。
1
2
3
import numpy as np
a = np.linspace(1, 10, 10)
print(a)

  1. 实例2:设置元素全部是1的等差数列。
1
2
3
4
import numpy as np

a = np.linspace(1, 1, 10)
print(a)

  1. 实例3:将 endpoint 设为 false,不包含终止值。
1
2
3
4
import numpy as np

a = np.linspace(10, 20, 5, endpoint=False)
print(a)

  1. 实例4:设置间距显示。
1
2
3
4
5
6
7
8
9
10
from cgitb import reset
from winreg import REG_WHOLE_HIVE_VOLATILE
import numpy as np

a = np.linspace(1, 10, 10, True, retstep=True)
print(a)

# 拓展例子
b = np.linspace(1, 10, 10).reshape([5, 2])
print(b)

6.3 numpy.logspace

  1. numpy.logspace 函数用于创建一个于等比数列,格式如下:
1
np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
  1. 参数说明
参数 描述
start 序列的起始值为:base ** start
stop 序列的终止值为:base ** stop。如果 endpoint 为 true,该值包含于数列中
num 要生成的等步长的样本数量,默认为 50
endpoint 该值为 true 时,数列中包含 stop 值,反之不包含,默认是 True。
base 对数 log 的底数。
dtype ndarray 的数据类型
  1. 实例
1
2
3
4
import numpy as np

a = np.logspace(0, 9, 10, endpoint=True, base=2)
print(a)


7 NumPy 切片和索引

7.1 基本索引和切片

  1. ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。
  2. ndarray 数组可以基于 0n 的切片进行索引,切片对象可以通过内置的 slice 函数,并设置 startstopstep 参数进行,从原数组中切割出一个新数组。
  3. 实例1
1
2
3
4
5
6
7
8
import numpy as np

a = np.arange(1, 10, 1)
print(a)
# 使用 slice 创建一个切片对象
s = slice(2, 7, 2)
print(s, type(s))
print(a[s])

  1. 实例2:我们也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作。
1
2
3
4
5
6
import numpy as np

a = np.arange(1, 10, 1, dtype=float)
print(a)
b = a[0:6:2]
print(b)

  1. 实例3:多维数组。
1
2
3
4
5
6
7
8
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a.shape)
print(a)
# 从某个索引开始切割
print("从数组索引 a[1:] 处开始切割")
print(a[1:])

7.2 省略号与冒号的关系

在 NumPy 中,省略号 ... 是一种特殊的切片符号,其核心作用是自动补全维度,让切片表达式的长度与数组的维度保持一致,从而简化多维数组的切片操作。

  1. 具体解释
    • 维度匹配原则

      • 当数组是多维时(如 2 维、3 维等),切片表达式的元素数量需要与数组的维度对应。例如,2 维数组需要用 [行切片, 列切片] 形式,3 维数组需要 [第1维切片, 第2维切片, 第3维切片]
      • 省略号 ... 会自动填充缺失的维度,确保切片表达式的长度与数组维度一致。
    • 行位置使用省略号的效果

      • 若在“行位置”使用 ...,表示匹配所有行维度,并对剩余维度进行切片。最终返回的结果是包含指定行中对应元素的 ndarray,且维度保持与原数组一致(仅切片部分元素,不改变维度数量)。
  2. 示例说明(以 2 维数组为例)
  • 假设有一个 2 维数组 a
1
2
3
4
import numpy as np
a = np.array([[1, 2, 3],
[3, 4, 5],
[4, 5, 6]])
  • 案例 1:a[..., 1](获取第 2 列元素)

    • 数组 a 是 2 维,切片表达式需要 2 个元素(行+列)。
    • ... 在这里代表“匹配所有行”,等价于 a[:, 1]: 表示所有行)。
    • 结果:[2, 4, 5](第 2 列的所有元素,保持 1 维数组形式)。
  • 案例 2:a[1, ...](获取第 2 行元素)

    • ... 代表“匹配所有列”,等价于 a[1, :]
    • 结果:[3, 4, 5](第 2 行的所有元素,保持 1 维数组形式)。
  • 案例 3:a[..., 1:](获取第 2 列及之后的所有元素)

    • ... 匹配所有行,1: 表示从第 2 列开始的所有列。
    • 结果:
      1
      2
      3
      [[2, 3],
      [4, 5],
      [5, 6]]

    (保持 2 维数组形式,仅切片列维度)。

  1. 延伸:省略号与冒号的关系
    • 省略号 ... 可以理解为“多个冒号 : 的简写”,具体等价于多少个冒号,取决于数组的维度。例如:
      • 对 3 维数组 bb[..., 0] 等价于 b[:, :, 0](匹配前两维的所有元素,切片第 3 维的第 0 个元素)。
      • 对 1 维数组 cc[...] 等价于 c[:](匹配唯一的维度,即所有元素)。

8 NumPy 高级索引

  1. NumPy 比一般的 Python 序列提供更多的索引方式。
  2. 除了之前看到的用整数和切片的索引外,数组可以由整数数组索引布尔索引花式索引
  3. NumPy 中的高级索引指的是使用整数数组布尔数组或者其他序列来访问数组的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。

8.1 整数数组索引

  1. 整数数组索引是指使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。
  2. 实例1:获取数组中 (0,0)、(1,1)和(2,0) 位置处的元素。
1
2
3
4
5
6
import numpy as np

x = np.array([[1, 2], [3, 4], [5, 6]])
# 获取数组中 (0,0)、(1,1)和(2,0) 位置处的元素
y = x[[0, 1, 2], [0, 1, 0]]
print(y)

  1. 实例2:获取 4X3 数组中的四个角的元素。 行索引是 [0,0] 和 [3,3],而列索引是 [0,2] 和 [0,2]。
1
2
3
4
5
6
7
8
9
10
11
import numpy as np 

x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
print ('我们的数组是:' )
print (x)
print ('\n')
rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]])
y = x[rows,cols]
print ('这个数组的四个角元素是:')
print (y)
  • 代码解读
    • 当使用两个形状相同的整数数组作为行索引和列索引时(如rows和cols),NumPy 会按位置一一对应的方式提取元素:
      • 行索引数组rows的每个元素,与列索引数组cols相同位置的元素组成一个坐标(rows[i,j], cols[i,j])
      • 最终结果的形状与索引数组的形状一致
    • 在代码中两个索引数组都是 2x2 的形状,对应关系如下:
      • rows[0,0] = 0 与 cols[0,0] = 0 → 坐标(0,0) → 元素0
      • rows[0,1] = 0 与 cols[0,1] = 2 → 坐标(0,2) → 元素2
      • rows[1,0] = 3 与 cols[1,0] = 0 → 坐标(3,0) → 元素9
      • rows[1,1] = 3 与 cols[1,1] = 2 → 坐标(3,2) → 元素11
    • 由于rows和cols都是 2x2 的数组,提取的元素按原位置排列,最终结果也是 2x2 的数组。
  1. 实例3:可以借助切片 : 与索引数组组合。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

# 定义一个 3×3 的数组
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# : 切片
b = a[1:3, 1:3]
c = a[1:3, [0, 2]]
d = a[..., 1:]
print(a)
print("---------")
print(b)
print("---------")
print(c)
print("---------")
print(d)

8.2 布尔索引

  1. 我们可以通过一个布尔数组来索引目标数组。
  2. 布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
  3. 实例1:获取大于 5 的元素。
1
2
3
4
5
6
7
8
9
import numpy as np

a = np.arange(12).reshape(4, 3)
print ('我们的数组是:')
print(a)
print("---------")
# 现在我们会打印出大于 5 的元素
print('大于 5 的元素是:')
print(a[a>5])

  1. 实例2:使用了 ~(取补运算符)来过滤 NaN
1
2
3
4
5
6
import numpy as np

a = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])
print(a[np.isnan(a)])
print('---------')
print(a[~np.isnan(a)])

  1. 实例3:从数组中过滤掉非复数元素。
1
2
3
4
5
6
import numpy as np

a = np.array([1, 2+6j, 5, 3.5+5j])
print(a[np.iscomplex(a)])
print('---------')
print(a[~np.iscomplex(a)])

8.3 花式索引

  1. 花式索引指的是利用整数数组进行索引。
  2. 花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。
  3. 对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素,如果目标是二维数组,那么就是对应下标的行。
  4. 花式索引跟切片不一样,它总是将数据复制到新数组中。

8.3.1 一维数组

  1. 一维数组只有一个轴 axis = 0,所以一维数组就在 axis = 0 这个轴上取值。
  2. 实例
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

x = np.arange(9)
print(x)

# 一维数组读取指定下标对应的元素
print("-------读取下标对应的元素-------")
x2 = x[[0, 6]]
print(x2)

print(x2[0])
print(x2[1])

8.3.2 二维数组

  1. 传入顺序索引数组。
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

x = np.arange(32).reshape((8, 4))
print(x)

# 二维数组读取指定下标对应的行
print("-------读取下标对应的行-------")
print(x[[4, 2, 1, 7]])

# 二维数组读取指定下标对应的元素
print("-------读取下标对应的元素-------")
print(x[[0, 1], [2, 3]])

  1. 传入倒序索引数组。
1
2
3
4
5
6
7
8
import numpy as np

x = np.arange(32).reshape((8, 4))
print(x)

# 二维数组读取指定下标对应的行
print("-------读取下标对应的行-------")
print(x[[-4, -2, -1, -7]])

  1. 传入多个索引数组(要使用 np.ix_
    1. np.ix_ 函数就是输入两个数组,产生笛卡尔积的映射关系。
    2. 笛卡尔乘积是指在数学中,两个集合 X 和 Y 的笛卡尔积(Cartesian product),又称直积,表示为X×YX \times Y,第一个对象是 X 的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。
    3. 例如 A={a,b}A=\{a,b\}B={0,1,2}B=\{0,1,2\},则:
      1. A×B={(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}A \times B = \{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)\}
      2. B×A={(0,a),(1,a),(2,a),(0,b),(1,b),(2,b)}B \times A = \{(0,a),(1,a),(2,a),(0,b),(1,b),(2,b)\}
1
2
3
4
5
6
7
8
import numpy as np

x = np.arange(32).reshape((8, 4))
print(x)

# 传入多个索引数组(要使用np.ix_)
print("---------")
print(x[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])])


9 NumPy 广播(Broadcast)

  1. 如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a×ba \times b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的长度相同。
1
2
3
4
5
import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
print(a*b)

  1. 广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。
  2. 广播的规则:
    1. 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
      1. 这里指的是在前面加 1 维,比如:(3,) 补齐为 (1, 3)。
    2. 输出数组的形状是输入数组形状的各个维度上的最大值。
    3. 如果输入数组的某个维度和输出数组的对应维度的大小相同或者大小为 1 时,会自动进行 stretching 扩展,否则报错。
  3. 当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制,如下演示:
1
2
3
4
5
6
7
8
import numpy as np

a = np.array([[0, 0, 0],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]])
b = np.array([0, 1, 2])
print(a + b)

  • 这里下图展示了该实例中广播机制的过程:

  1. 简单理解
    1. 对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
      1. 数组拥有相同形状;
      2. 当前维度的值相等;
      3. 当前维度的值有一个为 1。
    2. 若条件不满足,抛出 “ValueError: frames are not aligned” 异常。

10 NumPy 迭代数组

10.1 numpy.nditer

  1. NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。
  2. 迭代器最基本的任务是可以完成对数组元素的访问。
  3. 实例1:使用 arange() 函数创建一个 2X3 数组,并使用 nditer 对它进行迭代。
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

a = np.arange(6).reshape(2, 3)
print("原始数组是:")
print(a)
print("------")

print("迭代输出元素:")
for x in np.nditer(a):
print(x, end=", ")

print(np.nditer(a), type(np.nditer(a)))

以上实例不是使用标准 C 或者 Fortran 顺序,选择的顺序是和数组内存布局一致的,这样做是为了提升访问的效率,默认是行序优先(row-major order,或者说是 C-order)。这反映了默认情况下只需访问每个元素,而无需考虑其特定顺序。

  1. 实例2:通过迭代上述数组的转置来看到这一点,并与以 C 顺序访问数组转置的 copy 方式做对比。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

a = np.arange(6).reshape(2, 3)
print("原始数组是:")
print(a)
print("------")

print("转置数组是:")
print(a.T)
print("------")

for x in np.nditer(a.T):
print (x, end=", " )
print ('\n')

for x in np.nditer(a.T.copy(order='C')):
print (x, end=", " )

从上述例子可以看出,a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是 a.T.copy(order = 'C') 的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的,默认是按行访问。

  • 解读
    • 数组的内存存储顺序:NumPy 数组的存储顺序有两种
      • C 顺序(行优先):数组元素按行存储,即先存储第一行的所有元素,再存储第二行,以此类推。
      • Fortran 顺序(列优先):数组元素按列存储,即先存储第一列的所有元素,再存储第二列,以此类推。
      • 默认情况下,np.arange(6).reshape(2,3) 创建的数组 a 是 C 顺序存储的,内存中的元素排列为:[0, 1, 2, 3, 4, 5](对应数组[[0,1,2],[3,4,5]])。
    • 转置数组 a.T 的存储特性
      • 数组转置(a.T)会交换数组的维度(将2×3变为3×2),但不会改变原始数组的内存存储顺序
      • a的原始存储:[0, 1, 2, 3, 4, 5](C 顺序)。
      • a.T 的结构是 [[0,3], [1,4], [2,5]] ,但内存中仍沿用 a 的存储顺序[0,1,2,3,4,5](只是维度信息改变)。
    • 迭代a.T的结果
      • np.nditer 迭代数组时,默认按内存中的实际存储顺序访问元素,而非数组的维度结构。
      • 迭代 a.T 时,内存顺序仍是 [0,1,2,3,4,5] ,因此输出为:0, 1, 2, 3, 4, 5,。
    • a.T.copy(order='C')的作用:
      • copy(order='C')会重新按 C 顺序(行优先)复制数组到新内存,此时内存存储顺序会改变为 [0,3,1,4,2,5]。
      • a.T 的结构是[[0,3], [1,4], [2,5]],按 C 顺序存储时,内存中元素排列为[0,3,1,4,2,5](先存第一行[0,3],再存第二行[1,4],最后存第三行[2,5])。

10.2 控制遍历顺序

  1. for x in np.nditer(a, order='F'):Fortran order,即是列序优先。
  2. for x in np.nditer(a, order='C'):C order,即是行序优先。
  3. 实例1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np

a = np.arange(0, 60, 5).reshape(3, 4)
print("原始数组是:")
print(a)
print("------")

print("数组的转置是:")
b = a.T
print(b)
print("------")

print('以 C 风格顺序排序:')
c = b.copy(order='C')
print(c)
for x in np.nditer(c):
print (x, end=", " )
print ('\n')

print ('以 F 风格顺序排序:')
f = b.copy(order='F')
print(f)
for x in np.nditer(f):
print (x, end=", " )

  1. 实例2:可以通过显式设置,来强制 nditer 对象使用某种顺序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

a = np.arange(0, 60, 5).reshape(3, 4)
print('原始数组是:')
print(a)
print('------')

print('以 C 风格顺序排序:')
for x in np.nditer(a, order = 'C'):
print (x, end=", " )
print ('\n')

print('以 F 风格顺序排序:')
for x in np.nditer(a, order = 'F'):
print(x, end=", " )

10.3 修改数组中元素的值

  1. nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象read-only),为了在遍历数组的同时,实现对数组元素值的修改,必须指定 readwrite 或者 writeonly 的模式。
  2. 实例1
1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.arange(0, 60, 5).reshape(3, 4)
print ('原始数组是:')
print (a)
print('------')

for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2*x
print ('修改后的数组是:')
print (a)

  • 解读x[...] = 2*x
    • x 的本质:迭代器中的元素引用
      • 当使用 np.nditer 迭代数组时,变量 x 并不是原数组元素的直接引用,而是一个临时的“视图对象”(可以理解为元素的“视图”或“拷贝的引用”);
      • 如果直接使用 x = 2*x,只会修改这个临时对象 x 的值,不会影响原数组。
    • x[...]:强制修改原数组元素
      • x[...] 是 NumPy 中一种特殊的索引方式,称为省略号索引,它的作用是明确指定对原数组元素的修改
      • 这里的 …(省略号)表示“匹配所有维度”,由于迭代器每次访问的是数组中的单个元素(零维),x[...] 等价于直接引用原数组中当前迭代到的元素。
      • 因此,x[...]=2*x 的效果是:将当前元素 x 的值乘以 2 后,强制写回原数组对应的位置,从而实现对原数组的修改。

10.4 使用外部循环

  1. nditer 类的构造器拥有 flags 参数,它可以接受下列值:
参数 描述
c_index 可以跟踪 C 顺序的索引
f_index 可以跟踪 Fortran 顺序的索引
multi_index 每次迭代可以跟踪一种索引类型
external_loop 给出的值是具有多个值的一维数组,而不是零维数组
  1. 实例1:迭代器遍历对应于每列,并组合为一维数组。
1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.arange(0, 60 ,5).reshape(3, 4)
print ('原始数组是:')
print (a)
print('------')

print ('修改后的数组是:')
for x in np.nditer(a, flags=['external_loop'], op_flags=['readwrite'], order='F'):
x[...] = 2*x
print(x, end=', ')

10.5 广播迭代

  1. 如果两个数组是可广播的,nditer 组合对象能够同时迭代它们。假设数组 a 的维度为 3×43 \times 4,数组 b 的维度为 1×41 \times 4 ,则使用以下迭代器(数组 b 被广播到 a 的大小)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

a = np.arange(0, 60, 5).reshape(3, 4)
b = np.arange(0, 4, 1)
print('数组 a 是:')
print(a)
print('------')

print('数组 b 是:')
print(b)
print('------')

print('修改后的数组是:')
for x, y in np.nditer([a, b]):
print(f"{x}:{y}", end=', ')


11 NumPy 数组操作

11.1 修改数组形状

函数 描述
reshape 不改变数据的条件下修改形状
flat 数组元素迭代器
flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组
ravel 返回展开数组

11.1.1 numpy.reshape

  1. numpy.reshape 函数可以在不改变数据的条件下修改形状,格式如下:
1
numpy.reshape(arr, newshape, order='C')
  • 参数解读:
    • arr:要修改形状的数组
    • newshape:整数或者整数数组,新的形状应当兼容原有形状
    • order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序。
  1. 实例
1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.arange(8)
print ('原始数组:')
print (a)
print ('\n')

b = a.reshape(4,2)
print ('修改后的数组:')
print (b)

11.1.2 numpy.ndarray.flat

  1. numpy.ndarray.flat 是一个数组元素迭代器。
  2. 实例
1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.arange(9).reshape(3, 3)
print("原始数组:")
for row in a:
print(row)

# 对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器。
print("迭代后的数组:")
for element in a.flat:
print(element)

11.1.3 numpy.ndarray.flatten

  1. numpy.ndarray.flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组,格式如下:
1
ndarray.flatten(order='C')
  • 参数解读:
    • order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序。
  1. 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

a = np.arange(8).reshape(2, 4)
print("原始数组:")
print(a)
print("------")

# 默认按行
print("展开的数组:")
print(a.flatten())
print("------")

# 指定为列
print("展开的数组:")
print(a.flatten(order='F'))

11.1.4 numpy.ravel

  1. numpy.ravel() 展平的元素,顺序通常是“C风格”,返回的是数组视图(view,有点类似 C/C++ 引用 reference 的意味),修改会影响原始数组。
  2. 该函数接收两个参数:
1
numpy.ravel(a, order='C')
  • 参数解读:
    • a:输入数组
    • order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。
  1. 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np

a = np.arange(8).reshape(2, 4)
print("原始数组:")
print(a)
print("------")

print("调用ravel()函数:")
print(a.ravel())
print("------")

print("调用ravel()函数,指定order:")
print(a.ravel(order='F'))

11.2 翻转数组

函数 描述
transpose 对换数组的维度
ndarray.T 和 self.transpose() 相同
rollaxis 向后滚动指定的轴
swapaxes 对换数组的两个轴

11.2.1 numpy.transpose

  1. numpy.transpose 函数用于对换数组的维度,格式如下:
1
numpy.transpose(arr, axes)
  • 参数解读:
    • arr:要操作的数组
    • axes:整数列表,对应维度,通常所有维度都会对换。
  1. 实例1
1
2
3
4
5
6
7
8
9
import numpy as np

a = np.arange(8).reshape(2, 2, 2)
print("原始数组:")
print(a)
print("------")

print("调用transpose()函数:")
print(np.transpose(a))

注意:这里的对换是指对换数组的维度,而不是对换数组的元素。比如数字1,在原数组下角标为001,对换过后变为了100,属于循环置换(Cyclic Permutation)或循环轮换(Cyclic Rotation)。

  1. 实例2numpy.ndarray.T 类似 numpy.transpose
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

a = np.arange(8).reshape(2, 2, 2)
print("原始数组:")
print(a)
print("------")

print("调用transpose()函数:")
print(np.transpose(a))

print("调用ndarray.T属性:")
print(a.T)

11.2.2 numpy.rollaxis

  1. numpy.rollaxis 函数向后滚动特定的轴到一个特定位置,格式如下:
1
numpy.rollaxis(arr, axis, start)
  • 参数解读:
    • arr:要操作的数组
    • axis:要向后滚动的轴,其它轴的相对位置不会改变
    • start:默认为零,表示完整的滚动,会滚动到数组的最后一个轴。
  1. 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import numpy as np

# 创建了三维的 ndarray
a = np.arange(8).reshape(2,2,2)
print("原始数组:")
print(a)
print('获取数组中一个值:')
print(np.where(a==6))
print(a[1, 1, 0])
print("------")

# 将轴2滚动到轴0(宽度到深度)
print('调用 rollaxis 函数:')
b = np.rollaxis(a, 2, 0)
print(b)
print(b.shape)
# 查看元素 a[1,1,0],即 6 的坐标,变成 [0, 1, 1]
# 最后一个 0 移动到最前面
print('查看元素 a[1,1,0],即 6 的坐标:')
print(np.where(b==6))
print("------")

# 将轴 2 滚动到轴 1(宽度到高度)
print('调用 rollaxis 函数:')
c = np.rollaxis(a, 2, 1)
print(c)
# 查看元素 a[1,1,0],即 6 的坐标,变成 [1, 0, 1]
# 最后的 0 和 它前面的 1 对换位置
print(np.where(c==6))

11.2.3 numpy.swapaxes

  1. numpy.swapaxes 函数用于交换数组的两个轴,格式如下:
1
numpy.swapaxes(arr, axis1, axis2)
  • 参数解读:
    • arr:要操作的数组
    • axis1:要交换的第一个轴
    • axis2:要交换的第二个轴
  1. 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

# 创建了三维的 ndarray
a = np.arange(8).reshape(2,2,2)

print('原数组:')
print(a)
print(np.where(a==6))
print('------')

# 现在交换轴 0(深度方向)到轴 2(宽度方向)
print('调用 swapaxes 函数后的数组:')
b = np.swapaxes(a, 2, 0)
print(b)
print(np.where(b==6))
print('------')

# 现在交换轴 0(深度方向)到轴 1(高度方向)
print('调用 swapaxes 函数后的数组:')
c = np.swapaxes(a, 2, 1)
print(c)
print(np.where(c==6))
print('------')

11.3 修改数组维度

维度 描述
broadcast 产生模仿广播的对象
broadcast_to 将数组广播到新形状
expand_dims 扩展数组的形状
squeeze 从数组的形状中删除一维条目

11.3.1 numpy.broadcast

  1. numpy.broadcast 函数用于构造广播对象,它模拟了广播的过程,返回一个对象,该对象封装了将一个数组广播到另一个数组的结果。
  2. 实例:该函数使用两个数组作为输入参数。
1
code

11.4 连接数组

11.5 分割数组

11.6 数组元素的添加与删除