1.1 概念
-
NumPy 的全称是“ Numeric Python”,它是 Python 的第三方扩展包,主要用来计算、处理一维或多维数组
-
在数组算术计算方面, NumPy 提供了大量的数学函数
-
NumPy 的底层主要用 C语言编写,因此它能够高速地执行数值计算
-
NumPy 还提供了多种数据结构,这些数据结构能够非常契合的应用在数组和矩阵的运算上
1.2 优点
NumPy 可以很便捷高效地处理大量数据,使用 NumPy 做数据处理的优点如下:
-
NumPy 是 Python 科学计算基础库
-
NumPy 可以对数组进行高效的数学运算
-
NumPy 的 ndarray 对象可以用来构建多维数组
-
NumPy 能够执行傅立叶变换与重塑多维数组形状
-
NumPy 提供了线性代数,以及随机数生成的内置函数
1.3 与python列表区别
NumPy 数组是同质数据类型(homogeneous),即数组中的所有元素必须是相同的数据类型。数据类型在创建数组时指定,并且数组中的所有元素都必须是该类型。
Python 列表是异质数据类型(heterogeneous),即列表中的元素可以是不同的数据类型。列表可以包含整数、浮点数、字符串、对象等各种类型的数据。
NumPy 数组提供了丰富的数学函数和操作,如矩阵运算、线性代数、傅里叶变换等。
Python 列表提供了基本的列表操作,如添加、删除、切片、排序等。
1.4 安装
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple/
2.ndarray
NumPy 定义了一个 n 维数组对象,简称 ndarray 对象,它是一个一系列相同类型元素组成的数组集合。数组中的每个元素都占有大小相同的内存块,您可以使用索引或切片的方式获取数组中的每个元素。
ndarray 对象采用了数组的索引机制,将数组中的每个元素映射到内存块上,并且按照一定的布局对内存块进行排列,常用的布局方式有两种,即按行或者按列。
主要特点
-
多维数组:ndarray 可以表示任意维度的数组,包括一维、二维、三维等。
-
同质数据类型:ndarray 中的所有元素必须是相同的数据类型。
-
高效内存布局:ndarray 在内存中是连续存储的,这使得数组的访问和操作非常高效。
-
丰富的功能和方法:ndarray 提供了丰富的数学函数和操作,如矩阵运算、线性代数、傅里叶变换等。
使用方式:
-
ndarray 是通过 array 函数或其他 NumPy 函数(如 zeros、ones、arange 等)创建的。
-
array 函数接受一个序列作为输入,并返回一个 ndarray 对象。
2.1 array创建对象
通过 NumPy 的内置函数 array() 可以创建 ndarray 对象,其语法格式如下:
numpy.array(object, dtype = None, copy = True, order = None,ndmin = 0)
参数说明:
序号 | 参数 | 描述说明 |
---|---|---|
1 | object | 表示一个数组序列 |
2 | dtype | 可选参数,通过它可以更改数组的数据类型 |
3 | copy | 可选参数,表示数组能否被复制,默认是 True |
4 | order | 以哪种内存布局创建数组,有 3 个可选值,分别是 C(行序列)/F(列序列)/A(默认) |
5 | ndmin | 用于指定数组的维度 |
案例:
import numpy as np # 创建一个一维数组 def array_test_one():dimensionalArray = np.array([1,2,3,4])print("array 创建一维数组:",dimensionalArray)print("array 创建以为数组:",type(dimensionalArray))print("ndim 查看/指定数组维度:",dimensionalArray.ndim) # 创建一个二维数组 def array_test_two():dimensionalArray = np.array([[1,2,3,4],[5,6,7,8]])print("array 创建二维数组:",dimensionalArray)print("array 创建二维数组类型:",type(dimensionalArray))print("ndim 查看维度:",dimensionalArray.ndim)
2.2 ndim指定/查看数组维度
数组的维度就是一个数组中的某个元素,当用数组下标表示的时候,需要用几个数字来表示才能唯一确定这个元素,这个数组就是几维
案例:
import numpy as np # 指定/查看数组维度 def ndmin_test():threeArray = np.array([1,2,3,4],ndmin=2)print("ndmin 指定数组:",threeArray)print("ndmin 指定数组:",type(threeArray))print("ndim 查看维度:",threeArray.ndim)
2.3 reshape数组变维
reshape() 函数允许你在不改变数组数据的情况下,改变数组的维度。
reshape() 返回的是一个新的数组,原数组不会被修改。reshape() 可以用于多维数组,例如将一个一维数组重塑为二维数组。
元素总数必须匹配:新形状中的元素总数必须与原数组中的元素总数相同。
例如,一个长度为6的一维数组可以被重塑为 (2, 3) 或 (3, 2),但不能被重塑为 (2, 2)。
案例:
将数组改变为二维数组:
import numpy as np # 数组变维 def reshape_test():oneArray = np.array([1,2,3,4,5,6])print("oneArray 原数组内容:",oneArray)print("oneArray 原数组维度:",oneArray.ndim)oneArray = oneArray.reshape((3,2))print("oneArray 新数组内容:",oneArray)print("oneArray 新数组维度:",oneArray.ndim)
-1 作为占位符:你可以使用 -1 作为占位符,让 numpy 自动计算某个维度的大小。
例如:
import numpy as np # 数组变维 def reshape_test():oneArray = np.array([1,2,3,4,5,6])print("oneArray 原数组内容:",oneArray)print("oneArray 原数组维度:",oneArray.ndim)oneArray = oneArray.reshape((3,-1))print("oneArray 新数组内容:",oneArray)print("oneArray 新数组维度:",oneArray.ndim)
reshape() 还可以将一维数组重塑为三维数组:
例如:
import numpy as np # 创建一个一维数组 arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) # 使用 reshape() 函数将其转换为三维数组 reshaped_arr = arr.reshape((2, 3, 2)) print(reshaped_arr) print("ndim:", reshaped_arr.ndim)
说明:
reshape((2, 3, 2))表示将数组重塑为一个三维数组,其形状为 (2, 3, 2),具体来说,这个形状表示:
-
第一个维度:有 2 个元素。
-
第二个维度:每个元素有 3 个元素。
-
第三个维度:每个元素有 2 个元素。
具体过程:
首先,将一维数组分成 2 个部分:
[1, 2, 3, 4, 5, 6] 和 [7, 8, 9, 10, 11, 12]
然后,将每个部分分成 3 个部分:
[1, 2], [3, 4], [5, 6] 和 [7, 8], [9, 10], [11, 12]
最后,将每个部分分成 2 个部分,如:
[1, 2]
注意:形状 (2, 3, 2)中的参数个数相乘要等于数组中元素的个数,如:数组[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]有12个元素,形状(2,3,2)的参数相乘:2x3x2=12。
3.数据类型
NumPy 提供了比 Python 更加丰富的数据类型,如下所示:
序号 | 数据类型 | 语言描述 |
---|---|---|
1 | bool_ | 布尔型数据类型(True 或者 False) |
2 | int_ | 默认整数类型,类似于 C 语言中的 long,取值为 int32 或 int64 |
3 | intc | 和 C 语言的 int 类型一样,一般是 int32 或 int 64 |
4 | intp | 用于索引的整数类型(类似于 C 的 ssize_t,通常为 int32 或 int64) |
5 | int8 | 代表与1字节相同的8位整数。值的范围是-128到127 |
6 | int16 | 代表 2 字节(16位)的整数。范围是-32768至32767 |
7 | int32 | 代表 4 字节(32位)整数。范围是-2147483648至2147483647 |
8 | int64 | 表示 8 字节(64位)整数。范围是-9223372036854775808至9223372036854775807 |
9 | uint8 | 1字节(8位)无符号整数 |
10 | uint16 | 2 字节(16位)无符号整数 |
11 | uint32 | 4 字节(32位)无符号整数 |
12 | uint64 | 8 字节(64位)无符号整数 |
13 | float_ | float64 类型的简写 |
14 | float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10个尾数位 |
15 | float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23个尾数位 |
16 | float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52个尾数位 |
17 | complex_ | 复数类型,与 complex128 类型相同 |
18 | complex64 | 表示实部和虚部共享 32 位的复数 |
19 | complex128 | 表示实部和虚部共享 64 位的复数 |
20 | str_ | 表示字符串类型 |
21 | string_ | 表示字节串类型 |
3.1 数据类型对象
数据类型对象(Data Type Object)又称 dtype 对象,是用来描述与数组对应的内存区域如何使用。
1.可以在创建数组时指定 dtype 参数来定义数组中元素的数据类型。
例如:
import numpy as np # 创建一个 int32 类型的数组 arr_int = np.array([1, 2, 3], dtype=np.int32) print(arr_int.dtype) # 输出: int32 # 创建一个 float64 类型的数组 arr_float = np.array([1.0, 2.0, 3.0], dtype=np.float64) print(arr_float.dtype) # 输出: float64
2.可以使用数组的 dtype 属性来获取数组中元素的数据类型。
例如:
arr = np.array([1, 2, 3]) print(arr.dtype) # 输出: int32
3.可以使用 astype() 方法来转换数组中元素的数据类型。
例如:
arr = np.array([1, 2, 3]) arr_float = arr.astype(np.float64) print(arr_float.dtype) # 输出: float64
3.2 数据类型标识码
NumPy 中每种数据类型都有一个唯一标识的字符码,int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替,如下所示:
字符 | 对应类型 |
---|---|
b | 代表布尔型 |
i | 带符号整型 |
u | 无符号整型 |
f | 浮点型 |
c | 复数浮点型 |
m | 时间间隔(timedelta) |
M | datatime(日期时间) |
O | Python对象 |
S,a | 字节串(S)与字符串(a) |
U | Unicode |
V | 原始数据(void) |
以下是 NumPy 中常见的数据类型标识码及其对应的详细列表:
整数类型
标识码 | 数据类型 | 描述 |
---|---|---|
int8 | i1 | 8 位有符号整数 |
int16 | i2 | 16 位有符号整数 |
int32 | i4 | 32 位有符号整数 |
int64 | i8 | 64 位有符号整数 |
uint8 | u1 | 8 位无符号整数 |
uint16 | u2 | 16 位无符号整数 |
uint32 | u4 | 32 位无符号整数 |
uint64 | u8 | 64 位无符号整数 |
浮点数类型
标识码 | 数据类型 | 描述 |
---|---|---|
float16 | f2 | 16 位浮点数(半精度) |
float32 | f4 | 32 位浮点数(单精度) |
float64 | f8 | 64 位浮点数(双精度) |
复数类型
标识码 | 数据类型 | 描述 |
---|---|---|
complex64 | c8 | 64 位复数(单精度) |
complex128 | c16 | 128 位复数(双精度) |
布尔类型
标识码 | 数据类型 | 描述 |
---|---|---|
bool | b1 | 布尔类型 |
字符串类型
标识码 | 数据类型 | 描述 |
---|---|---|
S | S10 | 长度为 10 的字节串 |
U | U10 | 长度为 10 的 Unicode 字符串 |
Python 对象类型
标识码 | 数据类型 | 描述 |
---|---|---|
O | O | Python 对象类型 |
例如:自定义一个int32的数据类型
dt=np.dtype('i4') data = np.array([1,2,3,4],dtype=dt) print(data) #输出:[1 2 3 4] print(data.dtype) #输出:int32
可以自定义复杂的数据结构:
dt=np.dtype([('name','S10'),('age','i4')]) data = np.array([('zhangsan',20),('lisi',21)],dtype=dt) print(data) #输出:[(b'zhangsan', 20) (b'lisi', 21)] print(data.dtype) #输出:[('name', 'S10'), ('age', '<i4')]
说明:
在编程中,字节序标记用于指定数据的字节顺序。常见的字节序标记包括:
-
<
: 小端序,数据的最低有效字节存储在内存的最低地址,而最高有效字节存储在内存的最高地址。 -
>
: 大端序,数据的最高有效字节存储在内存的最低地址,而最低有效字节存储在内存的最高地址。
4.数组属性
4.1 shape
返回一个元组,元组中的每个元素表示数组在对应维度上的大小。元组的长度等于数组的维度数。
shape 属性功能:
-
未传入参数,返回一个由数组维度构成的元组
-
传入参数,可以用来调整数组维度的大小
def shape_test():array_one = np.array([[1,2,3],[4,5,6]])print('array_one 原数组维度:',array_one.shape)print('array_one 原数组内容:',array_one)array_one.shape = (3,2)print('array_one 转变数组维度大小之后的数组维度:',array_one.shape)print('array_one 转变数组维度大小之后的数组内容:',array_one)
如果使用shape属性修改数组的形状,则修改的是原数组的形状,reshape修改数组的形状会返回一个新数组,不修改原数组的形状。
4.2 ndim
ndim 属性功能:
-
返回的是数组的维数
4.3 itemsize
itemsize 属性功能:
-
返回数组中每个元素的大小(以字节为单位)
'''itemsize 属性功能:1、返回数组中每个元素的大小(以字节为单位) ''' def itemsize_test():array_one = np.array([[1,2,3],[4,5,6]],dtype=np.int8)print('array_one 数组中每个元素的大小:',array_one.itemsize) #输出:1array_one = np.array([[1,2,3],[4,5,6]],dtype=np.int16)print('array_one 数组中每个元素的大小:',array_one.itemsize) #输出:2
4.4 flags
flags 属性功能:
-
返回 ndarray 数组的内存信息
'''flags 属性功能:1、返回 ndarray 数组的内存信息 ''' def flags_test():array_one = np.array([[1,2,3],[4,5,6]])print('array_one 数数组的内存信息:\n',array_one.flags)
输出:
C_CONTIGUOUS : True F_CONTIGUOUS : False OWNDATA : True WRITEABLE : True ALIGNED : True WRITEBACKIFCOPY : False
说明:
C_CONTIGUOUS: 表示数组在内存中是 C 风格连续的(行优先)。 如果为 True,则数组是 C 风格连续的。 F_CONTIGUOUS: 表示数组在内存中是 Fortran 风格连续的(列优先)。 如果为 True,则数组是 Fortran 风格连续的。 OWNDATA: 表示数组是否拥有自己的数据。 如果为 True,则数组拥有自己的数据;如果为 False,则数组可能是从另一个数组或对象借用数据的。 WRITEABLE: 表示数组是否可写。 如果为 True,则数组是可写的;如果为 False,则数组是只读的。 ALIGNED: 表示数组是否对齐。 如果为 True,则数组的数据在内存中是对齐的。 WRITEBACKIFCOPY: 表示数组是否是通过 np.copy 创建的副本,并且需要将更改写回原始数组。 如果为 True,则数组是通过 np.copy 创建的副本,并且需要将更改写回原始数组。 UPDATEIFCOPY: 表示数组是否是通过 np.copy 创建的副本,并且需要将更改写回原始数组。 如果为 True,则数组是通过 np.copy 创建的副本,并且需要将更改写回原始数组。
5.创建数组的其他方法
5.1 empty()
empty() 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组(数组元素为随机值)
格式:
numpy.empty(shape, dtype = float, order = 'C')
参数 | 描述 |
---|---|
shape | 数组的形状,可以是整数或整数元组 |
dtype | 数组的数据类型,默认为 float |
order | 数组的内存布局,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序 |
案例:
import numpy as np '''empty 函数:1、用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组(数组元素为随机值) ''' def empty_test():array_one = np.empty(shape=(2,3),dtype='i1',order='C')print("empty 函数创建数组:",array_one)
5.2 zeros()
创建指定大小的数组,数组元素以 0 来填充
格式:
numpy.zeros(shape, dtype = float, order = 'C')
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | 'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组 |
案例:
import numpy as np '''zeros 函数:1、创建指定大小的数组,数组元素以 0 来填充 ''' def zeros_test():array_one = np.zeros(shape=(2,3),dtype='i1',order='C')print("zeros 函数创建数组:",array_one)
5.3 ones()
创建指定形状的数组,数组元素以 1 来填充
格式:
numpy.ones(shape, dtype = None, order = 'C')
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | 'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组 |
案例:
import numpy as np '''ones 函数:1、创建指定形状的数组,数组元素以 1 来填充 ''' def ones_test():array_one = np.ones(shape=(2,3),dtype='i1',order='C')print("zeros 函数创建数组:",array_one)
5.4 arange()
arange() 函数用于创建一个等差数列的数组。它类似于 Python 内置的 range() 函数,但返回的是一个 NumPy 数组而不是一个列表。
格式:
numpy.arange(start, stop, step, dtype)
根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个 ndarray。
参数 | 描述 |
---|---|
start | 起始值,默认为 0 |
stop | 终止值(不包含) |
step | 步长,默认为 1 |
dtype | 返回 ndarray 的数据类型,如果没有提供,则会使用输入数据的类型 |
案例1:
import numpy as np # 创建一个从 0 到 9 的数组 arr = np.arange(10) print(arr) # 输出: # [0 1 2 3 4 5 6 7 8 9]
案例2:
import numpy as np # 创建一个从 1 到 10 的数组 arr = np.arange(1, 11) print(arr) # 输出: # [ 1 2 3 4 5 6 7 8 9 10]
案例3:
import numpy as np # 创建一个从 0 到 10,步长为 2 的数组 arr = np.arange(0, 10, 2) print(arr) # 输出: # [0 2 4 6 8]
案例4:
import numpy as np # 创建一个从 10 到 0,步长为 -1 的数组 arr = np.arange(10, 0, -1) print(arr) # 输出: # [10 9 8 7 6 5 4 3 2 1]
案例5:
import numpy as np # 创建一个从 0 到 1,步长为 0.1 的浮点数数组 arr = np.arange(0, 1, 0.1) print(arr) # 输出: # [0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
注意:
-
arange() 函数生成的数组不包含 stop 值。
-
如果 step 为负数,则 start 必须大于 stop,否则生成的数组为空。
-
arange() 函数在处理浮点数时可能会出现精度问题,因为浮点数的表示和计算存在精度误差。
5.5 linspace
在指定的数值区间内,返回均匀间隔的一维等差数组,默认均分 50 份
格式:
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
参数 | 描述 |
---|---|
start | 起始值,默认为 0 |
stop | 终止值 |
num | 表示数值区间内要生成多少个均匀的样本,默认值为 50 |
endpoint | 默认为 True,表示数列包含 stop 终止值,反之不包含 |
retstep | 表示是否返回步长。如果为 True,则返回一个包含数组和步长的元组;如果为 False,则只返回数组。默认为 False。 |
dtype | 返回 ndarray 的数据类型,默认为 None,表示根据输入参数自动推断数据类型。 |
案例:
'''linspace 函数:1、在指定的数值区间内,返回均匀间隔的一维等差数组,默认均分 50 份 ''' def linspace_test():array_one = np.linspace(0,9,3,retstep=True,dtype='i1')print("linspace 函数创建数组:",array_one)
说明:以上几个函数通常用于创建数字类型的数组,也可以用于创建布尔、字符串等类型的数组。但更适合用于创建数字数组。
6.切片
ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样;
slice()
在 Python 中,slice 可以作为一个对象来使用。你可以创建一个 slice 对象,然后使用它来获取序列的片段。
参数:
-
start 是切片开始的位置(包含该位置)。
-
stop 是切片结束的位置(不包含该位置)。
-
step 是切片的步长,即选取元素的间隔。
案例:
import numpy as np '''slice 函数:1、从原数组的上切割出一个新数组 ''' def slice_test():array_one = np.array([1,2,3,4])print("array_one 数组内容:",array_one)result = slice(0,len(array_one),2)print("slice 截取 array_one 数组内容:",array_one[result])
slice 操作也可通过 [start:stop:step] 的形式来实现
import numpy as np def two():array_one = np.array([[1, 2, 3], [4, 5, 6]])print(array_one)print(array_one[..., 1]) # 第2列元素print(array_one[1,...]) # 第2行元素print(array_one[1:2, 1:2]) # 第2行第2列元素print(array_one[..., 1:]) # 第2列及剩下的所有元素
冒号 : 的作用
-
表示范围: 冒号用于表示一个范围。例如,array[1:3] 表示从索引 1 到索引 3(不包括 3)的元素。
-
表示所有元素: 单独使用冒号表示所有元素。例如,array[:, 1] 表示所有行的第 1 列。
-
步长: 双冒号后面可以跟一个步长值,表示每隔多少个元素取一个。例如,array[::2] 表示每隔一个元素取一个。
注:冒号对于一维数组按索引号截取,二维数组按行和列截取。
省略号 ... 的作用
-
表示所有维度: 省略号用于表示数组的所有维度。例如,array[..., 1] 表示取所有行的第 1 列。
-
简化多维切片: 在多维数组中,省略号可以简化切片操作,避免显式地写出所有维度的索引。
7.高级索引
NumPy 中的高级索引指的是使用整数数组、布尔数组或者其他序列来访问数组的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。
7.1 整数数组索引
整数数组索引是指使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。
案例:
import numpy as np def one():array_one = np.array([[1,2,3],[4,5,6]])print(array_one)# [0,1,0]代表行索引、[0,1,2]代表列索引;即取出索引坐标 (0,0)、(1,1)、(0,2) 的元素array_one = array_one[[0,1,0],[0,1,2]]print(array_one)
取出 4 * 3 数组四个角的数据:
import numpy as np def two():array_one = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])print('原数组:\n',array_one)array_one = array_one[[0,0,-1,-1], [0,-1,0,-1]]print('这个数组的四个角元素是:')print(array_one)
7.2 布尔索引
布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
案例1:一维数组的布尔索引
import numpy as np # 创建一个一维数组 arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # 使用布尔索引筛选大于 5 的元素 bool_idx = arr > 5 print(bool_idx) # 输出: [False False False False False True True True True True] # 使用布尔索引获取满足条件的元素 result = arr[bool_idx] print(result) # 输出: [ 6 7 8 9 10]
案例2:多维数组的布尔索引
import numpy as np # 创建一个二维数组 arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 使用布尔索引筛选大于 5 的元素 bool_idx = arr > 5 print(bool_idx) # 输出: # [[False False False] # [False False True] # [ True True True]] # 使用布尔索引获取满足条件的元素 result = arr[bool_idx] print(result) # 输出: [6 7 8 9]
案例3:
使用逻辑运算符(如 &、|、~)组合多个条件。
import numpy as np # 创建一个一维数组 arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # 使用布尔索引筛选大于 5 且小于 9 的元素 bool_idx = (arr > 5) & (arr < 9) print(bool_idx) # 输出: [False False False False False True True True False False] # 使用布尔索引获取满足条件的元素 result = arr[bool_idx] print(result) # 输出: [6 7 8]
逻辑运算符:
-
&:与运算,组合多个条件。
-
|:或运算,组合多个条件。
-
~:非运算,取反条件。
8.广播
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。这要求维数相同,且各维度的长度相同,如果不相同,可以通过广播机制,这种机制的核心是对形状较小的数组,在横向或纵向上进行一定次数的重复,使其与形状较大的数组拥有相同的维度。
广播规则
-
维度匹配:如果两个数组的维度数不同,维度数较少的数组会在前面补上长度为 1 的维度。
-
长度匹配:如果两个数组在某个维度上的长度不同,但其中一个数组在该维度上的长度为 1,则该数组会沿着该维度进行广播。
-
不匹配:如果两个数组在某个维度上的长度既不相同也不为 1,则广播失败,抛出 ValueError。
案例1:一维数组与标量相加
import numpy as np # 创建一个一维数组 arr = np.array([1, 2, 3]) # 标量相加 result = arr + 1 print(result) # 输出: [2 3 4]
标量 1 被广播到与 arr 相同的形状,然后进行逐元素相加。
案例2:二维数组与一维数组相加
import numpy as np # 创建一个二维数组 arr2d = np.array([[1, 2, 3], [4, 5, 6]]) # 创建一个一维数组 arr1d = np.array([10, 20, 30]) # 相加 result = arr2d + arr1d print(result) # 输出: # [[11 22 33] # [14 25 36]]
arr1d 被广播到与 arr2d 相同的形状,然后进行逐元素相加。
案例3:二维数组与二维数组相加
import numpy as np # 创建一个二维数组 arr2d = np.array([[1, 2, 3], [4, 5, 6]]) # 创建一个形状为 (1, 3) 的二维数组 arr2d_broadcast = np.array([[10, 20, 30]]) # 相加 result = arr2d + arr2d_broadcast print(result) # 输出: # [[11 22 33] # [14 25 36]]
arr2d_broadcast 被广播到与 arr2d 相同的形状,然后进行逐元素相加。
案例4:广播失败
import numpy as np # 创建一个二维数组 arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 创建一个形状为 (2, 3) 的二维数组 arr2d_broadcast = np.array([[10, 20, 30], [40, 50, 60]]) # 尝试相加 try:result = arr2d + arr2d_broadcast except ValueError as e:print(e) # 输出: operands could not be broadcast together with shapes (3,3) (2,3)