1、NumPy基础
1.1.安装和导入NumPy
1. 安装NumPy
在终端或命令行中运行以下命令:
pip install numpy
在终端或命令行中安装NumPy之前需要先安装Python。NumPy是Python的一个扩展库,依赖于Python环境,因此没有Python的话无法安装和使用NumPy。
如果你已经安装了Anaconda,可以用它来安装:
conda install numpy
conda 是 Anaconda 提供的包管理和环境管理工具。它能够安装、更新、卸载各种包(如 NumPy、Pandas 等)并管理不同的 Python 环境,让开发者更容易切换和管理不同项目所需的依赖库。conda 不仅支持 Python 包,还可以管理其他语言的包,因此比 pip 更强大。
2. 导入NumPy
安装完成后,在Python代码中导入NumPy通常使用import numpy as np,这使得后续使用NumPy时可以简化代码。
示例如下:
import numpy as np
现在,你可以使用 np 来调用NumPy的函数和属性了。
1.2.数组的基本概念(ndarray)
ndarray(N-dimensional array)是NumPy中用于表示多维数组的核心数据结构。它可以存储多维数据,例如一维数组、二维矩阵,甚至更高维度的数据。这使得 ndarray 非常适合处理数值计算、数据分析、机器学习等场景。下面是一些 ndarray 的基本概念和特点:
1. ndarray 的基本结构
ndarray 是一个多维、同质(即数组中所有元素类型相同)的数据容器。它由以下几部分组成:
数据类型 (dtype):指定数组中元素的类型,如整数 (int)、浮点数 (float)、布尔值等。形状 (shape):数组的维度信息。shape 属性表示每一维度的大小。维度 (ndim):数组的维数,表示该数组是几维的。大小 (size):数组中元素的总数量。
2. 创建 ndarray
可以使用 np.array() 方法将Python的列表或元组转换为 ndarray。例如:
import numpy as np
# 创建一维数组
arr1 = np.array([1, 2, 3, 4])
print(arr1) # 输出:[1 2 3 4]
# 创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2)
# 输出:
# [[1 2 3]
# [4 5 6]]
3.ndarray 的基本属性
每个 ndarray 对象都具有一些常用的属性,可以帮助我们了解数组的结构:
# 示例数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 数组的形状(shape)
print(arr.shape) # 输出:(2, 3)
# 数组的维度(ndim)
print(arr.ndim) # 输出:2
# 数组的大小(size)
print(arr.size) # 输出:6
# 数组的数据类型(dtype)
print(arr.dtype) # 输出:int64(或其他整数类型,取决于系统)
4. 多维数组
NumPy支持任意维度的数组,可以是1维、2维、3维,甚至更高维度。如下所示:
# 三维数组
arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(arr3)
# 输出:
# [[[1 2]
# [3 4]]
#
# [[5 6]
# [7 8]]]
5. ndarray 的特点
快速高效:ndarray 是基于C语言实现的,执行速度很快。广播机制:支持在不同形状的数组之间执行运算。支持多种运算:可以在数组上执行算术运算、逻辑运算、索引、切片等各种操作。
ndarray 是NumPy中最核心的对象,理解它有助于深入学习数值计算和数据处理。
1.3.数组基础
1.3.1.数据类型
1.整数型数组与浮点型数组
为了克服列表的缺点,一个NumPy数组只容纳一种数据类型,以节约内存。以整数型数组与浮点型数组为例:
import numpy as np
# 创建整数型数组
arr1 = np.array([1, 2, 3]) #元素若都是整型,则为整数型数组
print(arr1) # 输出: [1 2 3]
# 创建浮点型数组
arr2 = np.array([1.0, 2, 3]) #内含浮点数,则为浮点型数组
print(arr2) # 输出: [1. 2. 3.]
注意,使用 print 输出 NumPy 数组后,元素之间没有逗号,这有两个好处是可以可将之与 Python 列表区分开来,二是避免逗号与小数点之间的混淆。
2.同化定理
一个人的力量是无法改变全体的,在实际操作中要注意:
往整数型数组里插入浮点数,该浮点数会自动被截断为整数;往浮点型数组里插入整数,该整数会自动升级为浮点数;
import numpy as np
# 创建整数型数组
arr1 = np.array([1, 2, 3])
arr1[0] = 100.9 # 插入浮点数,被截断,数组仍为整数型
print(arr1) # 输出: [100 2 3]
# 创建浮点型数组
arr2 = np.array([1.0, 2, 3])
arr2[1] = 10 # 插入整数型,被升级,数组仍为浮点型
print(arr2) # 输出: [1. 10. 3.]
3.共同改变定理
同化定理告诉我们,整数型数组和浮点型数组之间的界限十分严格,那么如何将这两种数据类型的数组进行相互转化呢?既然某一个人容易被集体所同化那只要全体共同改变,自然就可以成功
整数型数组和浮点型数组相互转换,规范的方法是使用.astype()方法。
import numpy as np
# 创建整数型数组
arr1 = np.array([1, 2, 3])
print(arr1) # 输出: [1 2 3]
# 将整数型数组转换为浮点型数组
arr2 = arr1.astype(float)
print(arr2) # 输出: [1. 2. 3.]
# 将浮点型数组转换回整数型数组
arr3 = arr2.astype(int)
print(arr3) # 输出: [1 2 3]
除了上述方法,只要满足共同改变定理,整数型数组和浮点型数组仍然可以互相转换。最常见的是整数型数组在运算过程中升级为浮点型数组,示例如下:
import numpy as np
# 整数型数组
arr = np.array([1, 2, 3])
print(arr) # 输出: [1 2 3]
# 整数型数组与浮点数做运算
print(arr + 0.0) # 输出: [1. 2. 3.]
print(arr * 1.0) # 输出: [1. 2. 3.]
# 整数型数组遇到除法(即便是除以整数)
print(arr / 1) # 输出: [1. 2. 3.]
# 整数型数组与浮点型数组做运算
int_arr = np.array([1, 2, 3])
float_arr = np.array([1.0, 2, 3])
print(int_arr + float_arr) # 输出: [2. 4. 6.]
整数型数组很好升级,但浮点型数组在运算过程中一般不会降级。
1.3.2.数组维度
在深度学习中,三维及其以上的数组出现较少,因此主要讲解一维数组和二维数组。学习了一维和二维数组后,可以很容易地类推到三维数组。
不同维度数组的表示,从外观上的本质区别是:
一维数组使用1层中括号表示。
二维数组使用2层中括号表示。
三维数组使用3层中括号表示。
数组形状参数:
一维数组的形状参数形如:x或(x,)。二维数组的形状参数形如:(x, y)。三维数组的形状参数形如:(x, y, z)。
第一个维度(深度)有x个元素,第二个维度(行)有y个元素,第三个维度(列)有z个元素。
数组形状示例:
当数组有1层中括号,如[1, 2, 3],则其为一维数组,其形状是3或(3,)。
当数组有2层中括号,如[[1, 2, 3]],则其为二维数组,其形状是(1, 3)。
当数组有3层中括号,如[[[1, 2, 3]]],则其为三维数组,其形状是(1, 1, 3)。
这里用后面要讲的 np.ones( ) 函数进行演示,只因其刚好需要传入形状参数。
import numpy as np
#创建一维数组:
arr1 = np.ones(3)
print(arr1)#输出:[1. 1. 1.]
#创建二维数组
arr2 = np.ones((1, 3))
print(arr2)#输出:[[1. 1. 1.]]
#创建三维数组:
arr3 = np.ones((1, 1, 3))
print(arr3)#输出:[[[1. 1. 1.]]]
查看数组的形状:
print(arr1.shape)
print(arr2.shape)
print(arr3.shape)
#输出:
(3,)
(1, 3)
(1, 1, 3)
2、数组的创建
在NumPy中,可以使用多种方法创建数组。以下是一些常用的方法:
2.1. array()
array() 是最常用的创建数组的方法,可以将列表、元组等序列数据转换为 ndarray 数组。
import numpy as np
# 通过列表创建一维数组
arr1 = np.array([1, 2, 3, 4])
print(arr1) # 输出:[1 2 3 4]
# 通过嵌套列表创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2)
# 输出:
# [[1 2 3]
# [4 5 6]]
2.2. arange()
arange() 用于生成具有固定步长的等差数组,类似于 Python 的 range() 函数。
import numpy as np
# 创建一个从 0 到 9 的一维数组
arr = np.arange(10)
print(arr) # 输出:[0 1 2 3 4 5 6 7 8 9]
# 指定起始值、结束值和步长
arr_step = np.arange(2, 10, 2)
print(arr_step) # 输出:[2 4 6 8]
2.3. linspace()
linspace() 用于创建在指定范围内具有固定数量元素的等间隔数组,常用于生成连续的数据点。
import numpy as np
# 创建一个从 0 到 1 的数组,包含 5 个等间距的值
arr = np.linspace(0, 1, 5)
print(arr) # 输出:[0. 0.25 0.5 0.75 1. ]
# 创建一个从 0 到 10 的数组,包含 4 个等间距的值
arr_large = np.linspace(0, 10, 4)
print(arr_large) # 输出:[ 0. 3.33333333 6.66666667 10. ]
2.4. zeros()
zeros() 用于创建所有元素均为 0 的数组,适用于初始化需要全部为 0 的数组。
import numpy as np
# 创建一个一维零数组,长度为 5
arr = np.zeros(5)
print(arr) # 输出:[0. 0. 0. 0. 0.]
# 创建一个 2x3 的零矩阵
arr_2d = np.zeros((2, 3))
print(arr_2d)
# 输出:
# [[0. 0. 0.]
# [0. 0. 0.]]
2.5. ones()
ones() 用于创建所有元素均为 1 的数组,适合用于初始化需要全部为 1 的数组。
import numpy as np
# 创建一个一维数组,长度为 5,值全为 1
arr = np.ones(5)
print(arr) # 输出:[1. 1. 1. 1. 1.]
# 创建一个 2x3 的矩阵,值全为 1
arr_2d = np.ones((2, 3))
print(arr_2d)
# 输出:
# [[1. 1. 1.]
# [1. 1. 1.]]
2.6. eye()
eye() 创建一个单位矩阵,对角线元素为 1,其他元素为 0。
import numpy as np
# 创建一个 3x3 的单位矩阵
arr = np.eye(3)
print(arr)
# 输出:
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
2.7. random 模块
NumPy 的 random 模块提供了随机数生成的功能,可以生成各种随机数组。
np.random.rand()
生成0到1之间的均匀分布的浮点数,支持指定形状。
import numpy as np
# 生成一个随机浮点数数组,长度为5
arr = np.random.rand(5)
print(arr) # 输出类似:[0.26674455 0.85674365 0.83504875 0.0947853 0.59059363]
# 生成一个2x3的随机数组
arr_2d = np.random.rand(2, 3)
print(arr_2d)
#输出:[[0.53906339 0.94653916 0.48469193]
# [0.72947324 0.55864621 0.23548281]]
np.random.randint()
生成给定范围内的随机整数,支持指定形状。
# 生成1到10之间的一个随机整数
rand_int = np.random.randint(1, 10)
print(rand_int)#输出:9
# 生成1到10之间的2x3的随机整数数组
arr = np.random.randint(1, 10, size=(2, 3))
print(arr)
#输出:[[9 8 2]
# [9 8 5]]
np.random.randn()
生成标准正态分布(均值为0,标准差为1)的随机数,类似于 rand() 但符合正态分布。
# 生成一个长度为5的正态分布数组
arr = np.random.randn(5)
print(arr)#输出:[-0.14451857 0.46234321 0.75082202 -0.66510259 0.52073312]
# 生成一个2x3的正态分布数组
arr_2d = np.random.randn(2, 3)
print(arr_2d)
#输出:[[ 0.94489443 -0.36822856 1.80855408]
# [ 0.88469963 -0.35445813 -0.73938533]]
np.random.choice()
从给定的一维数组中随机抽取元素,允许指定抽取的数量以及是否放回(即可以重复抽取)。
# 从数组 [1, 2, 3, 4, 5] 中随机抽取一个元素
rand_choice = np.random.choice([1, 2, 3, 4, 5])
print(rand_choice)#输出:4
# 随机抽取3个元素,允许重复
arr_choice = np.random.choice([1, 2, 3, 4, 5], size=3, replace=True)
print(arr_choice)#输出:[1 3 3]
# 随机抽取3个元素,不允许重复
arr_choice_no_replace = np.random.choice([1, 2, 3, 4, 5], size=3, replace=False)
print(arr_choice_no_replace)#输出:[4 2 1]
np.random.shuffle()
在原数组上进行随机排列,改变数组的顺序(原地操作)。
arr = np.array([1, 2, 3, 4, 5])
np.random.shuffle(arr)
print(arr) # 输出顺序随机排列后的数组:[5 1 2 4 3]
np.random.permutation()
生成一个新的随机排列的数组,不改变原数组。
arr = np.array([1, 2, 3, 4, 5])
perm = np.random.permutation(arr)
print(perm) # 输出一个随机排列的数组:[5 4 1 2 3]
print(arr) # 原数组不变:[1 2 3 4 5]
np.random.uniform()
生成均匀分布的随机数,可以指定区间范围。
# 生成一个在1到10之间的均匀分布的随机数
rand_uniform = np.random.uniform(1, 10)
print(rand_uniform)#4.6469286168848845
# 生成一个2x3的均匀分布随机数组,区间为1到10
arr = np.random.uniform(1, 10, size=(2, 3))
print(arr)
#[[5.77040181 3.02357949 1.92100856]
# [4.72454165 8.63431945 5.43633303]]
np.random.normal()
生成正态分布的随机数,允许设置均值和标准差。
# 生成一个均值为0,标准差为1的正态分布随机数
rand_normal = np.random.normal(0, 1)
print(rand_normal)#1.180951257198756
# 生成一个2x3的正态分布数组,均值为5,标准差为2
arr = np.random.normal(5, 2, size=(2, 3))
print(arr)
#[[5.75662905 5.43292871 8.15551217]
# [6.76630693 4.04360497 6.49182055]]
3、数组的属性
在 NumPy 中,数组的属性用于描述数组的结构和数据特征。以下是对这些属性的详细说明:
3.1. shape:数组的形状
shape 是一个元组,表示数组在每个维度上的大小。它描述了数组的形状或布局。对于二维数组,shape 会返回 (行数, 列数);对于三维数组,返回 (深度, 行数, 列数),依此类推。
示例:
import numpy as np
# 创建一个2x3的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 查看数组的形状
print(arr.shape) # 输出:(2, 3),表示2行3列
可以通过修改 shape 属性来更改数组的形状:
# 将 2x3 的数组重塑为 3x2
arr.shape = (3, 2)
print(arr)
# 输出:
# [[1 2]
# [3 4]
# [5 6]]
3.2. ndim:数组的维度数
ndim 是一个整数,表示数组的维度数,即数组的“阶数”。ndim=1 表示一维数组,ndim=2 表示二维数组,以此类推。
示例:
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.ndim) # 输出:2,表示这是一个二维数组
3.3. size:数组中元素的总数
size 是一个整数,表示数组中所有元素的总数。这个值等于 shape 中所有维度大小的乘积。
示例:
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.size) # 输出:6,表示数组中总共有6个元素
3.4. dtype:数组的数据类型
dtype 表示数组中元素的数据类型,例如 int32、float64 等。数据类型可以在创建数组时指定,也可以在需要时使用 astype() 进行转换。
示例:
# 创建一个浮点数数组
arr_float = np.array([1.0, 2.0, 3.0])
# 查看数组的数据类型
print(arr_float.dtype) # 输出:float64
可以在创建数组时指定数据类型,或使用 astype() 方法更改数组的数据类型:
# 创建整数类型数组
arr_int = np.array([1, 2, 3], dtype=np.int32)
print(arr_int.dtype) # 输出:int32
# 转换为浮点数类型
arr_float = arr_int.astype(np.float64)
print(arr_float.dtype) # 输出:float64
4、数组的基本运算
4.1.算数运算
在 NumPy 中,算术运算可以直接在数组上逐元素进行。除了 Python 的算术运算符(如 +、- 等),NumPy 还提供了相应的函数(如 np.add()、np.subtract() 等),便于执行逐元素计算。
import numpy as np
# 创建两个数组
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
加法:+ 或 np.add()
逐元素相加,结果为每个对应元素的和。
# 使用运算符
# 使用运算符
result_add = a + b
print(result_add) # 输出:[ 6 8 10 12]
# 使用 np.add()
result_add_func = np.add(a, b)
print(result_add_func) # 输出:[ 6 8 10 12]
减法:- 或 np.subtract()
逐元素相减,结果为每个对应元素的差。
# 使用运算符
result_multiply = a - b
print(result_multiply) # 输出:[-4 -4 -4 -4]
# 使用 np.subtract()
result_multiply_func = np.subtract(a, b)
print(result_multiply_func) # 输出::[-4 -4 -4 -4]
乘法:* 或 np.multiply()
逐元素相乘,结果为每个对应元素的乘积。
# 使用运算符
result_multiply = a * b
print(result_multiply) # 输出:[ 5 12 21 32]
# 使用 np.multiply()
result_multiply_func = np.multiply(a, b)
print(result_multiply_func) # 输出:[ 5 12 21 32]
除法:/ 或 np.divide()
逐元素相除,结果为每个对应元素的商。
# 使用运算符
result_divide = a / b
print(result_divide) # 输出:[0.2 0.33333333 0.42857143 0.5 ]
# 使用 np.divide()
result_divide_func = np.divide(a, b)
print(result_divide_func) # 输出:[0.2 0.33333333 0.42857143 0.5 ]
指数运算:** 或 np.power()
逐元素计算幂次方。
# 使用运算符
result_power = a ** 2
print(result_power) # 输出:[ 1 4 9 16]
# 使用 np.power()
result_power_func = np.power(a, 2)
print(result_power_func) # 输出:[ 1 4 9 16]
取模:% 或 np.mod()
逐元素取余数。
# 使用运算符
result_mod = a % b
print(result_mod) # 输出:[1 2 3 4]
# 使用 np.mod()
result_mod_func = np.mod(a, b)
print(result_mod_func) # 输出:[1 2 3 4]
整除://或np.floor_divide()
逐元素整除。
# 使用运算符
result_floor_divide = b // a
print(result_floor_divide) # 输出:[5 3 2 2]
# 使用 np.floor_divide()
result_floor_divide_func = np.floor_divide(b, a)
print(result_floor_divide_func) # 输出:[5 3 2 2]
总结
运算运算符函数示例加法+np.add()a + b减法-np.subtract()a - b乘法*np.multiply()a * b除法/np.divide()a / b指数运算**np.power()a ** 2取模%np.mod()a % b整除//np.floor_divide()b // a4.2.数组与标量的运算
在 NumPy 中,数组可以与标量进行加、减、乘、除等算术运算。此类运算会自动应用到数组的每个元素上,即逐元素进行操作。这样可以快速对整个数组进行批量计算,而无需写循环。
import numpy as np
# 创建一个数组
arr = np.array([1, 2, 3, 4])
# 每个元素加 10
result_add = arr + 10
print("加法结果:", result_add) # 输出:[11 12 13 14]
# 每个元素减 2
result_subtract = arr - 2
print("减法结果:", result_subtract) # 输出:[-1 0 1 2]
# 每个元素乘 3
result_multiply = arr * 3
print("乘法结果:", result_multiply) # 输出:[ 3 6 9 12]
# 每个元素除以 2
result_divide = arr / 2
print("除法结果:", result_divide) # 输出:[0.5 1. 1.5 2. ]
# 每个元素求平方
result_power = arr ** 2
print("平方结果:", result_power) # 输出:[ 1 4 9 16]
#每个元素求余
result_mod = arr%2
print("求余数结果:"result_mod) # 输出;[1 0 1 0]
#每个元素整除
result_floor_divide = arr//2
print("求整除结果:"result_floor_divide) # 输出;[0 1 1 2]
说明:
数组与标量的运算在数组的每个元素上逐个进行,称为逐元素运算。NumPy 利用广播机制处理数组和标量的运算,使标量在内部扩展为与数组形状一致,从而完成计算。数组与标量的运算也可以通过函数进行计算,函数的使用同算数运算一致。
注意事项:
类型转换:运算结果的数据类型会根据数组和标量的数据类型自动调整。例如,如果数组是整数类型但与浮点数标量运算,结果会转成浮点数。
兼容性:数组与标量的运算可以适用于任何形状的数组(如一维、二维、三维等)。
4.3.比较运算
1、使用比较符号进行比较
在 NumPy 中,数组可以与标量或另一个数组进行比较运算,这些比较运算逐元素执行,并返回布尔值的数组,表示每个元素的比较结果。
import numpy as np
# 定义两个数组
a = np.array([1, 2, 3, 4])
b = np.array([2, 2, 4, 3])
等于 ==
#逐元素比较两个数组,返回每个位置是否相等。
result_eq1 = a == b
print("等于 (==):", result_eq1) # 输出:[False True False False]
#逐元素比较数组中的元素是否等于标量。
result_eq2 = a == 3
print("等于 (==):", result_eq2) # 输出:[False False True False]
不等于 !=
#逐元素比较两个数组,返回每个位置是否不相等。
result_neq1 = a != b
print("不等于 (!=):", result_neq1) # 输出:[ True False True True]
#逐元素比较数组中的元素是否不等于标量。
result_neq2 = a != 3
print("不等于 (!=):", result_neq2) # 输出:[ True True False True]
大于 >
#逐元素比较第一个数组是否大于第二个数组的对应元素。
result_gt1 = a > b
print("大于 (>):", result_gt1) # 输出:[False False False True]
#逐元素比较数组中的元素是否大于标量。
result_gt2 = a > 3
print("大于 (>):", result_gt2) # 输出:[False False False True]
小于 <
#逐元素比较第一个数组是否小于第二个数组的对应元素。
result_lt1 = a < b
print("小于 (<):", result_lt1) # 输出:[ True False True False]
#逐元素比较数组中的元素是否小于标量。
result_lt2 = a < 3
print("小于 (<):", result_lt2) # 输出:[ True True False False]
大于等于 >=
#逐元素比较第一个数组是否大于等于第二个数组的对应元素。
result_ge1 = a >= b
print("大于等于 (>=):", result_ge1) # 输出:[False True False True]
#逐元素比较数组中的元素是否大于等于标量。
result_ge2 = a >= 3
print("大于等于 (>=):", result_ge2) # 输出:[False False True True]
小于等于 <=
#逐元素比较第一个数组是否小于等于第二个数组的对应元素。
result_le1 = a <= b
print("小于等于 (<=):", result_le1) # 输出:[ True True True False]
#逐元素比较数组中的元素是否小于等于标量。
result_le2 = a <= 3
print("小于等于 (<=):", result_le2) # 输出:[ True True True False]
2、使用函数进行比较
在 NumPy 中,除了使用 ==、!=、>、<、>= 和 <= 直接进行比较运算外,还可以使用对应的函数来进行逐元素比较。以下是每种比较运算的函数:
比较运算的函数
运算符函数说明==np.equal()检查是否相等!=np.not_equal()检查是否不相等>np.greater()检查是否大于
示例代码
import numpy as np
# 定义两个数组
a = np.array([1, 2, 3, 4])
b = np.array([2, 2, 3, 1])
# 使用比较函数
print("等于 (np.equal):", np.equal(a, b)) # 输出:[False True True False]
print("不等于 (np.not_equal):", np.not_equal(a, b)) # 输出:[ True False False True]
print("大于 (np.greater):", np.greater(a, b)) # 输出:[False False False True]
print("小于 (np.less):", np.less(a, b)) # 输出:[ True False False False]
print("大于等于 (np.greater_equal):", np.greater_equal(a, b)) # 输出:[False True True True]
print("小于等于 (np.less_equal):", np.less_equal(a, b)) # 输出:[ True True True False]
说明
这些函数适用于数组与数组之间的比较,或者数组与标量之间的比较。
返回值是一个布尔数组,表示每个位置的比较结果。
4.4.逻辑运算
1、在布尔数组上使用逻辑运算符
在 NumPy 中,逻辑运算符 &、|、~ 和 ^ 可用于对布尔数组进行逐元素的逻辑操作。以下是每种逻辑运算的详细说明和示例:
import numpy as np
# 创建两个布尔数组
a = np.array([True, False, True, False])
b = np.array([True, True, False, False])
逻辑与 (&或np.logical_and())
逐元素执行逻辑与操作,仅当两个数组的对应元素都为 True 时返回 True,否则返回 False。
result_and = a & b
print("逻辑与 (&):", result_and) # 输出:[ True False False False]
逻辑或(|或np.logical_or())
逐元素执行逻辑或操作,只要两个数组的对应元素中有一个为 True 就返回 True,否则返回 False。
result_or = a | b
print("逻辑或 (|):", result_or) # 输出:[ True True True False]
逻辑非( ~或np.logical_not())
逐元素对数组进行逻辑非操作,即将 True 转为 False,将 False 转为 True。
result_not = ~a
print("逻辑非 (~):", result_not) # 输出:[False True False True]
逻辑异或 (^或np.logical_xor())
逐元素执行逻辑异或操作,仅当两个数组的对应元素一个为 True 且另一个为 False 时返回 True,否则返回 False。
result_xor = a ^ b
print("逻辑异或 (^):", result_xor) # 输出:[False True True False]
2、NumPy 的逻辑运算函数
NumPy 也提供了函数形式的逻辑运算,这些函数可以处理不同数据类型的数组,并且可以指定输出的数据类型。下面是如何使用这些函数的例子:
np.logical_and(a, b):执行逻辑与操作。np.logical_or(a, b):执行逻辑或操作。np.logical_not(a):执行逻辑非操作。np.logical_xor(a, b):执行逻辑异或操作。
这些函数可以接受一个额外的参数 dtype,用于指定输出数组的数据类型。如果没有指定 dtype,则输出数组的数据类型将自动决定,以能够表示操作结果。
示例代码
import numpy as np
a = np.array([True, False, True, True])
b = np.array([True, True, False, False])
# 逻辑与操作
result_and = np.logical_and(a, b)
print("Logical AND:", result_and)
# 逻辑或操作
result_or = np.logical_or(a, b)
print("Logical OR:", result_or)
# 逻辑非操作
result_not = np.logical_not(a)
print("Logical NOT:", result_not)
# 逻辑异或操作
result_xor = np.logical_xor(a, b)
print("Logical XOR:", result_xor)
# 指定输出类型为 int8
result_and_int8 = np.logical_and(a, b, dtype=np.int8)
print("Logical AND with int8:", result_and_int8)
输出结果:
Logical AND: [ True False False True]
Logical OR: [ True True True True]
Logical NOT: [False True False False]
Logical XOR: [False True True False]
Logical AND with int8: [1 0 0 1]
请注意,np.logical_and 和 np.logical_or 函数要求输入数组中的元素是布尔类型。如果数组包含非布尔类型的元素,你需要先将它们转换为布尔类型,或者使用按位逻辑运算符(&, |, ^)来执行操作。
3、在整数数组上使用逻辑运算符的操作
NumPy 的逻辑运算符 &、|、~ 和 ^ 可以用于整数型数组。不过,它们在整数数组上表现为逐元素的位运算,而不是逻辑运算:
示例代码
import numpy as np
# 定义两个整数数组
a = np.array([1, 2, 3, 4]) # 二进制表示为 [0001, 0010, 0011, 0100]
b = np.array([4, 5, 6, 7]) # 二进制表示为 [0100, 0101, 0110, 0111]
逐位与 &
result_and = a & b
print("逐位与 (&):", result_and) # 输出:[0, 0, 2, 4]
逐位或 |
result_or = a | b
print("逐位或 (|):", result_or) # 输出:[5, 7, 7, 7]
逐位非 ~
result_not = ~a
print("逐位非 (~):", result_not) # 输出:[-2, -3, -4, -5]
逐位异或 ^
result_xor = a ^ b
print("逐位异或 (^):", result_xor) # 输出:[5, 7, 5, 3]
注意事项
若要在布尔值意义上使用逻辑运算,可以将整数数组与逻辑条件结合使用,例如 (a > 2) & (b < 6),这样条件语句会返回布尔数组,再对其进行逻辑运算。
4.5.矩阵运算
在 NumPy 中,矩阵运算支持多种操作,包括矩阵乘法、转置、逆矩阵、行列式和特征值等。这些操作适用于线性代数计算和科学计算。以下是一些常用的矩阵运算方法:
矩阵乘法
矩阵乘法不同于逐元素乘法,可以通过 @ 运算符或 np.dot() 函数实现。
import numpy as np
# 定义两个矩阵
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 使用 @ 进行矩阵乘法
result_matmul = A @ B
print("矩阵乘法 (A @ B):\n", result_matmul)
#输出:
#矩阵乘法 (A @ B):
# [[19 22]
# [43 50]]
# 使用 np.dot() 进行矩阵乘法
result_dot = np.dot(A, B)
print("矩阵乘法 (np.dot(A, B)):\n", result_dot)
#输出:
#矩阵乘法 np.dot(A, B):
# [[19 22]
# [43 50]]
矩阵转置
矩阵转置可以使用 .T 属性或 np.transpose() 函数。
# 矩阵 A 的转置
A_T = A.T
print("矩阵转置 (A.T):\n", A_T)
#输出:
#矩阵转置 (A.T):
# [[1 3]
# [2 4]]
# 使用 np.transpose()
A_T_func = np.transpose(A)
print("矩阵转置 (np.transpose(A)):\n", A_T_func)
#输出:
#矩阵转置 np.transpose(A):
# [[1 3]
# [2 4]]
逆矩阵
矩阵的逆可以使用 np.linalg.inv() 函数,前提是矩阵必须是方阵,且行列式不为零。
# 计算 A 的逆矩阵
A_inv = np.linalg.inv(A)
print("逆矩阵 (np.linalg.inv(A)):\n", A_inv)
#输出:
#逆矩阵 (np.linalg.inv(A)):
# [[-2. 1. ]
# [ 1.5 -0.5]]
行列式
行列式可以用 np.linalg.det() 函数计算。
# 计算 A 的行列式
det_A = np.linalg.det(A)
print("行列式 (np.linalg.det(A)):", det_A)
#输出:行列式 (np.linalg.det(A)): -2.0
特征值和特征向量
可以使用 np.linalg.eig() 函数来计算方阵的特征值和特征向量。
调用 np.linalg.eig() 将返回两个数组:一个包含特征值,另一个包含对应的特征向量。
np.linalg.eigvals() 是 NumPy 中用于计算矩阵特征值的函数,但不同于 np.linalg.eig(),它只返回特征值,而不返回对应的特征向量。
# 计算 A 的特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)
#输出:
#特征值: [-0.37228132 5.37228132]
#特征向量:
# [[-0.82456484 -0.41597356]
# [ 0.56576746 -0.90937671]]
矩阵的范数
使用 np.linalg.norm() 计算矩阵的范数。
# 计算矩阵 A 的范数
norm_A = np.linalg.norm(A)
print("矩阵的范数 (np.linalg.norm(A)):", norm_A)
#矩阵的范数 (np.linalg.norm(A)): 5.477225575051661
点积(逐元素乘积)
可以用 * 进行逐元素乘法(Hadamard 乘积),不等同于矩阵乘法。
# 逐元素乘积
elementwise_product = A * B
print("逐元素乘积 (A * B):\n", elementwise_product)
#输出:
#逐元素乘积 (A * B):
# [[ 5 12]
# [21 32]]
在 NumPy 中,聚合运算用于对数组中的元素进行汇总计算,例如求和、求平均值、求最大值和最小值等。这些操作非常高效,广泛用于数据分析和统计。
4.6.聚合运算
操作函数说明求和np.sum()计算数组所有元素的和求平均值np.mean()计算数组所有元素的平均值求最大值np.max()返回数组的最大值求最小值np.min()返回数组的最小值求乘积np.prod()计算数组所有元素的乘积标准差np.std()计算数组所有元素的标准差方差np.var()计算数组所有元素的方差中位数np.median()计算数组的中位数累积和np.cumsum()返回数组的累积和累积积np.cumprod()返回数组的累积积最大值索引np.argmax()返回数组中最大值的索引最小值索引np.argmin()返回数组中最小值的索引1、一维数组的聚合运算
import numpy as np
# 定义一个数组
a = np.array([1, 2, 3, 4, 5])
#求和 np.sum()
print("求和:", np.sum(a)) # 输出:15
#求平均值 np.mean()
print("平均值:", np.mean(a)) # 输出:3.0
#求最大值 np.max()
print("最大值:", np.max(a)) # 输出:5
# 求最小值 np.min()
print("最小值:", np.min(a)) # 输出:1
#求乘积 np.prod()
print("乘积:", np.prod(a)) # 输出:120
#标准差 np.std()
print("标准差:", np.std(a)) # 输出:1.4142135623730951
#方差 np.var()
print("方差:", np.var(a)) # 输出:2.0
#中位数 np.median()
print("中位数:", np.median(a)) # 输出:3.0
#累积和 np.cumsum()
print("累积和:", np.cumsum(a)) # 输出:[ 1 3 6 10 15]
#累积积 np.cumprod()
print("累积积:", np.cumprod(a)) # 输出:[ 1 2 6 24 120]
#最大值索引 np.argmax()
print("最大值索引:", np.argmax(a)) # 输出:4
#最小值索引 np.argmin()
print("最小值索引:", np.argmin(a)) # 输出:0
解释:累计和(np.cumsum())和 累计积(np.cumprod())是两种逐元素的累积操作,它们分别返回数组中每个元素从头到当前元素的和或积。
2、多维数组的聚合运算
NumPy 提供了多种聚合运算,可以对数组在指定维度上进行汇总操作。这些聚合运算支持 axis 参数,可以选择在行、列或更深维度上执行。
import numpy as np
# 定义一个二维数组
a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 求和
print("沿行(axis=0)求和:", np.sum(a, axis=0)) # [12, 15, 18]
print("沿列(axis=1)求和:", np.sum(a, axis=1)) # [6, 15, 24]
print("数组总和:", np.sum(a)) # 45
# 求平均值
print("沿行(axis=0)求平均值:", np.mean(a, axis=0)) # [4, 5, 6]
print("沿列(axis=1)求平均值:", np.mean(a, axis=1)) # [2, 5, 8]
print("数组均值:", np.mean(a)) # 5.0
# 求最大值
print("沿行(axis=0)最大值:", np.max(a, axis=0)) # [7, 8, 9]
print("沿列(axis=1)最大值:", np.max(a, axis=1)) # [3, 6, 9]
print("数组最大值:", np.max(a)) # 9
# 求最小值
print("沿行(axis=0)最小值:", np.min(a, axis=0)) # [1, 2, 3]
print("沿列(axis=1)最小值:", np.min(a, axis=1)) # [1, 4, 7]
print("数组最小值:", np.min(a)) # 1
# 求乘积
print("沿行(axis=0)求乘积:", np.prod(a, axis=0)) # [28, 80, 162]
print("沿列(axis=1)求乘积:", np.prod(a, axis=1)) # [6, 120, 504]
print("数组乘积:", np.prod(a)) # 362880
# 标准差
print("沿行(axis=0)标准差:", np.std(a, axis=0)) # [2.45, 2.45, 2.45]
print("沿列(axis=1)标准差:", np.std(a, axis=1)) # [0.82, 0.82, 0.82]
print("数组标准差:", np.std(a)) # 2.581988897471611
# 方差
print("沿行(axis=0)方差:", np.var(a, axis=0)) # [6, 6, 6]
print("沿列(axis=1)方差:", np.var(a, axis=1)) # [0.67, 0.67, 0.67]
print("数组方差:", np.var(a)) # 6.666666666666667
# 中位数
print("沿行(axis=0)中位数:", np.median(a, axis=0)) # [4, 5, 6]
print("沿列(axis=1)中位数:", np.median(a, axis=1)) # [2, 5, 8]
print("数组中位数:", np.median(a)) # 5.0
# 累积和
print("沿行(axis=0)累积和:\n", np.cumsum(a, axis=0))
# [[ 1, 2, 3],
# [ 5, 7, 9],
# [12, 15, 18]]
print("沿列(axis=1)累积和:\n", np.cumsum(a, axis=1))
# [[ 1, 3, 6],
# [ 4, 9, 15],
# [ 7, 15, 24]]
print("数组累积和:\n", np.cumsum(a))
# [ 1 3 6 10 15 21 28 36 45]
# 累积积
print("沿行(axis=0)累积积:\n", np.cumprod(a, axis=0))
# [[ 1, 2, 3],
# [ 4, 10, 18],
# [ 28, 80, 162]]
print("沿列(axis=1)累积积:\n", np.cumprod(a, axis=1))
# [[ 1, 2, 6],
# [ 4, 20, 120],
# [ 7, 56, 504]]
print("数组累积积:\n", np.cumprod(a))
# [ 1 2 6 24 120 720 5040 40320 362880]
# 最大值索引
print("沿行(axis=0)最大值索引:", np.argmax(a, axis=0)) # [2, 2, 2]
print("沿列(axis=1)最大值索引:", np.argmax(a, axis=1)) # [2, 2, 2]
print("数组最大值索引:", np.argmax(a)) # 8
# 最小值索引
print("沿行(axis=0)最小值索引:", np.argmin(a, axis=0)) # [0, 0, 0]
print("沿列(axis=1)最小值索引:", np.argmin(a, axis=1)) # [0, 0, 0]
print("数组最小值索引:", np.argmin(a)) # 0
解释
axis=0 表示沿着行方向聚合(计算每一列的聚合结果)。axis=1 表示沿着列方向聚合(计算每一行的聚合结果)。不指定 axis 则对整个数组进行运算,返回一个单一的值。对于 3D 数组或更高维度的数组,可以选择任意一个轴进行聚合。例如,对于一个 3x3x3 数组,可以指定 axis=0、axis=1 或 axis=2。
4.7.广播机制
在 NumPy 中,广播(Broadcasting)机制用于处理不同形状的数组之间的算术运算。当两个数组的形状不同,但符合某些条件时,NumPy 会自动将较小数组的形状扩展为与较大数组相同的形状,以便进行逐元素运算,而无需复制数据。
广播机制的规则
广播机制遵循以下规则:
如果两个数组的维度不同,则在较小维度的前面填充1,直到两个数组的维数相同。例如,形状为 (3, ) 的数组会被当成 (1, 3)。
如果两个数组的形状在任何一个维度上不匹配,则其中一个维度必须为1。这种情况下,NumPy 会在那个维度上将大小为1的数组“扩展”以匹配另一个数组。例如,形状为 (4, 3) 和 (1, 3) 的数组可以进行广播,因为第一个数组在第一个维度是4,第二个数组在第一个维度是1。
如果两个数组在任一维度上都不相等且没有1,则无法广播,会产生错误。
广播的示例
数组与标量的广播
当数组和标量进行运算时,标量会自动扩展为与数组相同的形状。
import numpy as np
a = np.array([1, 2, 3])
b = 2
# 标量 2 被广播为与 a 相同形状的数组 [2, 2, 2]
result = a + b
print(result) # 输出:[3, 4, 5]
不同维度的数组广播
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([1, 2, 3])
# b 的形状为 (3,),会先扩展为(1,3),然后广播为 (2, 3) 以匹配 a 的形状
result = a + b
print(result)
# 输出:
# [[2, 4, 6],
# [5, 7, 9]]
更复杂的广播
a = np.array([1, 2, 3]).reshape(3, 1)
b = np.array([4, 5, 6])
# a 的形状是 (3, 1),b 的形状是 (3,)被扩展成(1,3)
# a 会被广播为 (3, 3),b 会被广播为 (3, 3)
result = a + b
print(result)
# 输出:
# [[5, 6, 7],
# [6, 7, 8],
# [7, 8, 9]]
广播失败的情况
如果两个数组无法满足广播机制的规则,会抛出错误。例如:
a = np.array([1, 2, 3])
b = np.array([1, 2])
# 这会产生错误,因为数组 a 的形状是 (3,) 而 b 的形状是 (2,)
# 无法在任一维度上进行广播
result = a + b # ValueError
4.8.数学函数
在 NumPy 中,提供了多种数学函数,可以对数组进行基本的数学运算,这些函数支持逐元素操作,且通常能自动应用广播机制,使得不同形状的数组也能进行计算。
函数说明示例np.abs()绝对值np.abs([-1, -2, 3])np.sqrt()平方根np.sqrt([4, 9, 16])np.exp()指数运算(e 的幂次)np.exp([1, 2, 3])np.log()自然对数(ln)np.log([1, np.e, np.e**2])np.log10()以 10 为底的对数np.log10([10, 100, 1000])np.power()幂运算np.power([2, 3, 4], 2)np.sin()正弦np.sin([0, np.pi/2, np.pi])np.cos()余弦np.cos([0, np.pi/2, np.pi])np.tan()正切np.tan([0, np.pi/4, np.pi/2])np.arcsin()反正弦np.arcsin([0, 0.5, 1])np.arccos()反余弦np.arccos([1, 0.5, 0])np.arctan()反正切np.arctan([0, 1, np.inf])np.sinh()双曲正弦np.sinh([0, 1, 2])np.cosh()双曲余弦np.cosh([0, 1, 2])np.tanh()双曲正切np.tanh([0, 1, 2])np.floor()向下取整np.floor([1.7, 2.3, 3.8])np.ceil()向上取整np.ceil([1.2, 2.8, 3.1])np.round()四舍五入np.round([1.5, 2.3, 3.7])常见数学函数示例:
import numpy as np
# 示例数组
a = np.array([1, 2, 3, 4])
b = np.array([0.5, 1.5, 2.5, 3.5])
# 1. 绝对值
print("绝对值 np.abs(a):", np.abs(a)) #[1 2 3 4]
# 2. 平方根
print("平方根 np.sqrt(a):", np.sqrt(a))#[1. 1.41421356 1.73205081 2. ]
# 3. 指数运算(e 的幂次方)
print("指数运算 np.exp(a):", np.exp(a))#[ 2.71828183 7.3890561 20.08553692 54.59815003]
# 4. 自然对数(ln)
print("自然对数 np.log(a):", np.log(a))# [0. 0.69314718 1.09861229 1.38629436]
# 5. 对数运算(以 10 为底)
print("对数运算(以 10 为底)np.log10(a):", np.log10(a))#[0. 0.30103 0.47712125 0.60205999]
# 6. 幂运算
print("幂运算 np.power(a, 3):", np.power(a, 3))#[ 1 8 27 64]
# 7. 三角函数
print("正弦 np.sin(b):", np.sin(b))# [ 0.47942554 0.99749499 0.59847214 -0.35078323]
print("余弦 np.cos(b):", np.cos(b))#[ 0.87758256 0.0707372 -0.80114362 -0.93645669]
print("正切 np.tan(b):", np.tan(b))#[ 0.54630249 14.10141995 -0.7470223 0.37458564]
# 8. 反三角函数
print("反正弦 np.arcsin(b / 4):", np.arcsin(b / 4)) # 将值归一化到 [-1, 1] 范围
print("反余弦 np.arccos(b / 4):", np.arccos(b / 4))
print("反正切 np.arctan(b):", np.arctan(b))
# 9. 双曲函数
print("双曲正弦 np.sinh(b):", np.sinh(b))
print("双曲余弦 np.cosh(b):", np.cosh(b))
print("双曲正切 np.tanh(b):", np.tanh(b))
# 10. 舍入函数
print("向下取整 np.floor(b):", np.floor(b))#[0. 1. 2. 3.]
print("向上取整 np.ceil(b):", np.ceil(b))#[1. 2. 3. 4.]
print("四舍五入 np.round(b):", np.round(b))#[0. 2. 2. 4.]必须大于x.5才会变成x+1.(x为任意数)
5、数组索引与切片
在 NumPy 中,数组索引和切片用于访问和修改数组中的元素、子数组,支持对多维数组进行灵活的选择和操作。以下是数组索引和切片的基本方法和示例。
5.1. 普通索引
对于一维数组,可以使用与 Python 列表类似的索引方式:
import numpy as np
a = np.array([10, 20, 30, 40, 50])
# 访问第一个元素
print("第一个元素:", a[0])#第一个元素: 10
# 访问最后一个元素
print("最后一个元素:", a[-1])#最后一个元素: 50
对于二维或更高维数组,可以使用逗号分隔的索引来访问特定元素。
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 访问第一行第二列的元素
print("第一行第二列的元素:", b[0, 1])#第一行第二列的元素: 2
# 访问最后一行最后一列的元素
print("最后一行最后一列的元素:", b[-1, -1])#最后一行最后一列的元素: 9
5.2. 布尔索引
布尔索引是一种通过布尔条件来选择数组中满足条件的元素的方式。在 NumPy 中,可以使用布尔数组或布尔条件来筛选数组中的元素。
1.使用布尔条件筛选
我们可以对数组应用条件表达式,得到一个布尔数组,然后用这个布尔数组来选择满足条件的元素。
import numpy as np
# 创建一个示例数组
a = np.array([10, 15, 20, 25, 30])
# 筛选出所有大于 20 的元素
result = a[a > 20]
print("大于 20 的元素:", result)#大于 20 的元素: [25 30]
在这个例子中,a > 20 生成了一个布尔数组 [False, False, False, True, True],然后 a[a > 20] 使用该布尔数组从原数组中筛选出 25 和 30。
2.多条件筛选
可以使用逻辑运算符 &(和)、|(或)等来组合多个条件。
# 筛选出大于 15 且小于 30 的元素
result = a[(a > 15) & (a < 30)]
print("大于 15 且小于 30 的元素:", result)#大于 15 且小于 30 的元素: [20 25]
3.布尔数组作为索引
也可以直接创建一个布尔数组用于索引。这种方式对于需要用固定的布尔模式筛选元素的情况非常方便。
# 创建一个布尔数组
bool_index = np.array([True, False, True, False, True])
# 使用布尔数组索引
result = a[bool_index]
print("通过布尔数组筛选的元素:", result)#通过布尔数组筛选的元素: [10 20 30]
这里,布尔数组 [True, False, True, False, True] 用来选择 a 中的第 0、2 和 4 个元素。
4.修改满足条件的元素
布尔索引也可以用于修改满足条件的元素。
# 将所有小于 20 的元素修改为 0
a[a < 20] = 0
print("小于 20 的元素修改为 0 后的数组:", a)#小于 20 的元素修改为 0 后的数组: [ 0 0 20 25 30]
5. 布尔索引在多维数组中的应用
布尔索引同样适用于多维数组。条件表达式会返回一个形状相同的布尔数组,用于选择多维数组中的特定元素。
# 创建一个二维数组
b = np.array([[10, 15, 20], [25, 30, 35], [40, 45, 50]])
# 筛选出二维数组中大于 30 的元素
result = b[b > 30]
print("二维数组中大于 30 的元素:", result)#二维数组中大于 30 的元素: [35 40 45 50]
布尔索引是一种强大的方式,可以快速筛选和修改数组中的元素。它使得条件筛选和修改数组更加简洁、灵活。
5.3. 花式索引
普通索引用一层中括号,花式索引用两层中括号。花式索引允许通过数组的索引列表选取特定位置的元素。
# 创建一个示例一维数组
a = np.array([10, 20, 30, 40, 50])
# 使用索引数组 [0, 2, 4] 选取特定位置的元素
print("特定位置的元素:", a[[0, 2, 4]])#特定位置的元素: [10 30 50]
# 创建一个示例二维数组
b = np.array([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])
# 使用行索引和列索引选择元素
# 选择位置为 (0, 1), (1, 2), (2, 0) 的元素
row_indices = [0, 1, 2]
col_indices = [1, 2, 0]
result = b[row_indices, col_indices]
print("使用花式索引选择的元素:", result)#使用花式索引选择的元素: [20 60 70]
注意
索引数组的长度相同:在花式索引中,行索引数组和列索引数组的长度必须相同。返回一维数组:花式索引会返回一个一维数组,包含了选择的元素。支持多维数组:花式索引不仅适用于二维数组,还可以用于更高维的数组。
5.4. 数组切片
NumPy 数组支持切片操作,允许选择连续的子数组,使用语法 array[start:stop:step]。
语法 array[start:stop:step]参数含义:
start:切片的起始索引(包含)。如果省略,则默认为数组的第一个元素。
stop:切片的终止索引(不包含)。切片会取到 stop - 1 索引的元素。如果省略,则默认为数组的最后一个元素。
step:切片的步长(间隔)。如果省略,则默认为 1。
一维数组切片
c = np.array([10, 20, 30, 40, 50])
# 从索引 1 到索引 3 的元素
print("切片 [1:4]:", c[1:4])#切片 [1:4]: [20 30 40]
# 每隔一个元素取一个值
print("切片 [::2]:", c[::2])#切片 [::2]: [10 30 50]
多维数组切片
切片语法 array[start:stop:step] 可以在多维数组中应用,通过逗号分隔每个维度的切片。
d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 选取第 1 至第 2 行的所有列
print("第 1 至第 2 行的所有列:", d[0:2, :])#第 1 至第 2 行的所有列: [[1 2 3]
# [4 5 6]]
# 选取第 1 至第 2 列的所有行
print("第 1 至第 2 列的所有行:", d[:, 0:2])#第 1 至第 2 列的所有行: [[1 2]
# [4 5]
# [7 8]]
# 从第二行开始选取每隔一行的元素
print("隔行选取每隔一列的元素:", d[1::2, ::2])#隔行选取每隔一列的元素: [[4 6]]
5.5. 修改数组元素
在 NumPy 中,我们可以通过索引和切片来修改数组中的元素。以下是一些常见的方法来修改数组元素:
1. 使用单个索引修改元素
可以直接使用索引来访问并修改单个元素。
import numpy as np
# 创建一个一维数组
a = np.array([1, 2, 3, 4, 5])
# 修改索引 2 的元素
a[2] = 10
print("修改后的数组:", a) #修改后的数组: [ 1 2 10 4 5]
2. 使用切片修改一部分元素
可以通过切片选择数组中的多个元素,并对它们进行批量修改。
# 修改索引 1 到 3 的元素(不包括 3)
a[1:3] = [20, 30]
print("切片修改后的数组:", a) #切片修改后的数组: [ 1 20 30 4 5]
3. 使用布尔索引修改元素
布尔索引可以用来选择满足某些条件的元素,并对这些元素进行修改。
# 修改数组中大于 10 的元素,将它们设置为 100
a[a > 10] = 100
print("布尔索引修改后的数组:", a) #布尔索引修改后的数组: [ 1 100 100 4 5]
4. 多维数组元素的修改
对于多维数组,可以使用行和列的索引或切片来选择特定的元素或子数组进行修改。
# 创建一个二维数组
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 修改第 0 行第 1 列的元素
b[0, 1] = 20
# 修改第 1 行的所有元素
b[1, :] = [40, 50, 60]
print("多维数组修改后的数组:\n", b)
#多维数组修改后的数组:
# [[ 1 20 3]
# [40 50 60]
# [ 7 8 9]]
5. 使用np.where()进行条件修改
np.where() 通过条件找到索引位置,然后修改这些位置的元素。这通常在需要灵活设置不同值时会更方便。
# 将数组中所有大于 5 的元素设为 0
a[np.where(a > 5)] = 0
print("使用 np.where 修改后的数组:", a)#使用 np.where 修改后的数组:[ 1 0 0 4 5]
6. 使用 np.put 修改指定位置的元素
numpy.put(a, ind, v, mode='raise')
a: 输入数组,您希望在其中修改元素。
ind: 需要修改的元素的索引,可以是一个整数或整数数组。v: 新的值,可以是一个标量或与 ind 相同形状的数组。mode: (可选)决定如何处理索引超出范围的情况。默认值为 'raise',这意味着如果索引超出范围,将引发错误。另一个选项是 'wrap',它会将超出范围的索引循环回数组的开头。
一维数组的用法
下面是一个基本示例,展示如何使用 np.put() 来修改数组中的特定元素。
import numpy as np
# 创建一个一维数组
arr = np.array([10, 20, 30, 40, 50])
# 使用 np.put 修改索引 1 和 3 的元素
np.put(arr, [1, 3], [100, 200])
print("使用 np.put 修改后的数组:", arr)#使用 np.put 修改后的数组: [ 10 100 30 200 50]
在这个例子中,np.put() 函数在索引 1 和 3 的位置上分别替换了数组的元素,将其修改为 100 和 200。
多维数组的用法
np.put() 也可以用于多维数组,但在这种情况下,它会展平数组(将其视为一维数组)并按顺序处理索引。
# 创建一个二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
# 使用 np.put 修改元素
np.put(arr2d, [0, 3], [10, 20])
print("二维数组使用 np.put 修改后的数组:\n", arr2d)
#二维数组使用 np.put 修改后的数组:
# [[10 2 3]
# [20 5 6]]
在这个例子中,np.put() 将元素 [1, 4] 修改为 [10, 20]。注意,数组被视为一个一维数组,因此索引 0 和 3 分别对应于元素 1 和 4。
处理超出范围的索引
如果指定的索引超出了数组的范围,np.put() 默认会引发错误。
# 创建一个数组
arr = np.array([1, 2, 3])
# 尝试使用超出范围的索引
try:
np.put(arr, [0, 5], [10, 20]) # 索引 5 超出范围
except IndexError as e:
print("错误信息:", e)
#错误信息: index 5 is out of bounds for axis 0 with size 3
使用 mode 参数
可以使用 mode 参数来控制超出范围的行为。
# 使用 'wrap' 模式
arr = np.array([1, 2, 3, 4, 5])
np.put(arr, [0, 5], [10, 20], mode='wrap') # 索引 5 会循环到 0
print("使用 wrap 模式后的数组:", arr)#使用 wrap 模式后的数组: [20 2 3 4 10]
在这个例子中,索引 5 循环回到 0,因此元素 20 被放置在数组的第一个位置。
5.6.数组赋值
在 NumPy 中,数组赋值的确有时只是绑定(reference),而不是创建一个新的数组副本。理解这一点非常重要,因为它直接影响到对数组的操作及其可能产生的副作用。
1、直接赋值
当你将一个数组赋值给另一个变量时,两个变量将引用同一个数组,而不是创建一个新的数组副本。
import numpy as np
# 创建一个数组
a = np.array([1, 2, 3, 4, 5])
# 将数组 a 赋值给 b
b = a
# 修改 b 中的元素
b[0] = 10
print("a 数组:", a) # a 也会改变
print("b 数组:", b) # b 的修改反映在 a 上
#a 数组: [10 2 3 4 5]
#b 数组: [10 2 3 4 5]
在这个例子中,b 只是对 a 的一个引用,因此对 b 的修改也会影响到 a。
2、np.copy()赋值
为了避免这种绑定的行为,可以使用 np.copy() 创建一个数组的副本。副本是一个新的数组,修改副本不会影响原始数组。
# 使用 np.copy 创建 a 的副本
c = np.copy(a)
# 修改 c 中的元素
c[1] = 20
print("a 数组:", a) # a 不会改变
print("c 数组:", c) # c 的修改不影响 a
#a 数组: [10 2 3 4 5]
#c 数组: [10 20 3 4 5]
3、总结
赋值是引用:在 NumPy 中,赋值操作通常是对数组的引用,这意味着两个变量指向同一个数据存储区域。使用 np.copy():如果希望创建一个独立的副本,可以使用 np.copy(),这样对副本的修改将不会影响原始数组。谨慎处理:在进行数组赋值时,需小心处理引用,以避免意外修改数据。
6、数组的变形
在 NumPy 中,数组的变形操作包含多种方法,可以实现转置、翻转、重塑、拼接和分裂。以下是这几种常用变形操作的具体方法和示例:
6.1. 数组的转置
转置操作会将数组的行和列互换。NumPy 提供了 transpose()、T 属性、swapaxes() 等方法可以来实现转置。以下是对每个方法的详细说明及示例。
1. transpose()
功能:
transpose() 函数用于交换数组的维度顺序。对于二维数组,它等效于矩阵的转置操作(交换行和列);对于多维数组,它可以调整维度的顺序,形成不同排列。
语法:
numpy.transpose(arr, axes=None)
参数:
arr:需要转置的数组。axes:指定维度的顺序(可选)。如果没有提供,维度会被反转。
返回值:返回一个新数组,该数组是输入数组维度的重新排列视图。
示例:
二维数组的转置:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
transposed_arr = np.transpose(arr)
print("原始数组:\n", arr)
print("转置后的数组:\n", transposed_arr)
输出:
原始数组:
[[1 2 3]
[4 5 6]]
转置后的数组:
[[1 4]
[2 5]
[3 6]]
多维数组指定轴的交换:
arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
transposed_arr3d = np.transpose(arr3d, (1, 0, 2))
print("原始数组:\n", arr3d)
print("转置后的数组 (指定维度顺序):\n", transposed_arr3d)
输出:
原始数组:
[[[1 2]
[3 4]]
[[5 6]
[7 8]]]
转置后的数组 (指定维度顺序):
[[[1 2]
[5 6]]
[[3 4]
[7 8]]]
2.T 属性
功能:
T 属性是 NumPy 中用于转置数组的快捷方式,专门用于二维数组的行列互换操作。它不支持多维数组的维度重新排列,仅对数组的最后两个轴进行交换。
语法:
arr.T
参数:无
返回值:返回一个转置后的数组(视图)。
示例:
arr = np.array([[1, 2, 3], [4, 5, 6]])
transposed_arr_T = arr.T
print("原始数组:\n", arr)
print("使用 T 属性转置后的数组:\n", transposed_arr_T)
输出:
原始数组:
[[1 2 3]
[4 5 6]]
使用 T 属性转置后的数组:
[[1 4]
[2 5]
[3 6]]
说明:
T 仅在二维数组上生效,效果和 transpose() 类似。T 属性比 transpose() 更简洁,适合只需要基本转置操作的场景。
3. swapaxes()
功能:
swapaxes() 用于交换多维数组的两个指定轴。与 transpose() 不同,它不会改变所有轴的顺序,仅交换指定的两个轴,这对于高维数组的轴转换操作非常灵活。
语法:
numpy.swapaxes(arr, axis1, axis2)
参数:
arr:输入数组。axis1:要交换的第一个轴。axis2:要交换的第二个轴。
返回值:返回一个新的数组(视图),交换了指定轴。
示例:
二维数组的轴交换:
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
swapped_arr2d = arr2d.swapaxes(0, 1)
print("原始数组:\n", arr2d)
print("交换轴后的数组:\n", swapped_arr2d)
输出:
原始数组:
[[1 2 3]
[4 5 6]]
交换轴后的数组:
[[1 4]
[2 5]
[3 6]]
三维数组的轴交换:
arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
swapped_arr3d = arr3d.swapaxes(0, 2)
print("原始数组:\n", arr3d)
print("交换轴后的数组:\n", swapped_arr3d)
输出:
原始数组:
[[[1 2]
[3 4]]
[[5 6]
[7 8]]]
交换轴后的数组:
[[[1 5]
[3 7]]
[[2 6]
[4 8]]]
说明:
swapaxes() 是针对多维数组非常灵活的轴交换方法,适用于只想交换特定两个维度的场景。swapaxes() 可以实现复杂的轴重排,而不需要重新组织所有轴顺序。
4.总结对比
方法适用情况功能语法示例transpose()二维或多维数组可以交换多个维度顺序,形成任意顺序的排列np.transpose(arr)T 属性二维数组快捷实现二维数组的转置,仅用于行列互换arr.Tswapaxes()二维或多维数组交换指定的两个轴,适合高维数组中单独交换两维的情况arr.swapaxes(0, 1)
6.2.数组的翻转
在 NumPy 中,数组的反转(reversing an array)指的是将数组的元素顺序进行翻转。反转可以在不同的维度上进行,例如沿着行、列或特定的轴反转数组。这对于数据处理、分析以及在图像处理等领域中非常有用。
1.np.flip()
np.flip() 函数用于沿指定轴反转数组。如果未指定轴,将反转所有维度上的顺序。
语法:np.flip(arr, axis=None)
arr:要反转的数组。axis:指定沿哪个轴反转。默认为 None,即所有轴都反转。
示例:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 沿行反转 (轴=0)
print(np.flip(arr, axis=0))
# 输出:
# [[4 5 6]
# [1 2 3]]
# 沿列反转 (轴=1)
print(np.flip(arr, axis=1))
# 输出:
# [[3 2 1]
# [6 5 4]]
2. np.flipud() 和 np.fliplr()
这些是 np.flip() 的简化版本,专门用于二维数组的行或列方向反转。
np.flipud():沿垂直轴(上下)反转,类似于 np.flip(arr, axis=0)。np.fliplr():沿水平轴(左右)反转,类似于 np.flip(arr, axis=1)。
示例:
# 上下翻转
print(np.flipud(arr))
# 输出:
# [[4 5 6]
# [1 2 3]]
# 左右翻转
print(np.fliplr(arr))
# 输出:
# [[3 2 1]
# [6 5 4]]
3.使用切片 [::-1] 进行反转
使用切片 [::-1] 可以在数组的特定维度上实现反转。
示例:
# 一维数组反转
arr1d = np.array([1, 2, 3, 4])
print(arr1d[::-1]) # 输出: [4 3 2 1]
# 二维数组行反转(等同于 np.flip(arr, axis=0))
print(arr[::-1])
# 输出:
# [[4 5 6]
# [1 2 3]]
# 二维数组列反转
print(arr[:, ::-1])
# 输出:
# [[3 2 1]
# [6 5 4]]
4.高维数组的反转
对于高维数组,np.flip() 也可以指定轴,以便在不同维度上进行反转。
示例:
arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
# 沿第 0 轴反转
print(np.flip(arr3d, axis=0))
# 输出:
# [[[5 6]
# [7 8]]
#
# [[1 2]
# [3 4]]]
# 沿第 1 轴反转
print(np.flip(arr3d, axis=1))
# 输出:
# [[[3 4]
# [1 2]]
#
# [[7 8]
# [5 6]]]
# 沿第 2 轴反转
print(np.flip(arr3d, axis=2))
# 输出:
# [[[2 1]
# [4 3]]
#
# [[6 5]
# [8 7]]]
总结
方法描述示例np.flip(arr, axis=0)沿指定轴翻转(所有维度反转)np.flip(arr, axis=0)np.flipud(arr)沿垂直方向(上下)反转np.flipud(arr)np.fliplr(arr)沿水平方向(左右)反转np.fliplr(arr)[::-1]使用切片反转一维数组或特定轴上的元素顺序arr[::-1], arr[:, ::-1]这些反转方法可以帮助高效、灵活地调整数组元素顺序,从而在多种场景中满足数据处理需求。
6.3. 数组的重塑
数组的重塑(reshape)是指将一个数组重新组织成不同的形状,而不改变数据的本质。NumPy 提供了多种重塑数组的方式,这对于数据分析和机器学习任务中的数据处理很有用。
1. 使用 reshape() 方法
reshape() 方法可以将数组重新定义为指定的形状,只要新形状的元素总数与原数组相同。其常见语法是 array.reshape(new_shape)。
示例:
import numpy as np
# 创建一个一维数组
arr = np.array([1, 2, 3, 4, 5, 6])
# 将其重塑为 2x3 的二维数组
reshaped_arr = arr.reshape(2, 3)
print(reshaped_arr)
# 输出:
# [[1 2 3]
# [4 5 6]]
2. 自动推断维度:-1
使用 -1 作为 reshape() 中的某个维度,NumPy 会自动计算该维度的大小,使得新数组的总大小与原数组一致。适合用于未知维度的数据重塑。
示例:
# 自动推断行数,使数组为 3 列
reshaped_arr1 = arr.reshape(-1, 3)
print(reshaped_arr1)
# 输出:
# [[1 2 3]
# [4 5 6]]
# 自动推断行数,使数组为 3 行
reshaped_arr2 = arr.reshape(3, -1)
print(reshaped_arr2)
print(arr)
# 输出:
#[[1 2]
# [3 4]
# [5 6]]
#[1 2 3 4 5 6]
3.np.resize() 方法
resize() 不同于 reshape(),它不受元素总数限制,会直接更改数组的形状并填充或删除数据以满足新形状需求。若元素不足,会循环填充;多余元素会被截断。
示例:
# 改变形状为 2x4(比原数组多了两个元素)
resized_arr = np.resize(arr, (2, 4))
print(resized_arr)
print(arr)
# 输出:
# [[1 2 3 4]
# [5 6 1 2]]
# [1 2 3 4 5 6]
4. ravel() 和 flatten() 方法
ravel():返回一个展开的一维数组,是原数组的“视图”。flatten():返回一个展开的一维数组,是原数组的“副本”。
示例:
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
# 使用 ravel() 展开
print(arr2d.ravel()) # 输出: [1 2 3 4 5 6]
# 使用 flatten() 展开
print(arr2d.flatten()) # 输出: [1 2 3 4 5 6]
视图和副本
视图(View)
当我们创建一个数组的“视图”时,它与原数组共享相同的数据内存。即使数组形状或视图方式不同,视图中的任何更改会直接反映在原数组上。视图是原数组的另一种“窗口”,并没有复制数据。
示例:
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
view_arr = arr[:3] # 创建前3个元素的视图
view_arr[0] = 100 # 修改视图中的第一个元素
print(arr) # 输出:[100, 2, 3, 4, 5]
在此示例中,对 view_arr 的更改也会影响到 arr,因为它们共享数据内存。
常见的视图创建方式:切片操作(arr[start:stop:step])、ravel()(在适当情况下)、reshape()(在适当情况下)等。
副本(Copy)
当我们创建一个数组的“副本”时,NumPy 会生成一个新的数组对象,并分配独立的数据内存。副本中的任何更改不会影响原数组。
示例:
arr = np.array([1, 2, 3, 4, 5])
copy_arr = arr[:3].copy() # 创建前3个元素的副本
copy_arr[0] = 100 # 修改副本中的第一个元素
print(arr) # 输出:[1, 2, 3, 4, 5]
在此示例中,修改 copy_arr 的值不会影响到原数组 arr。
常见的副本创建方式:copy() 函数、flatten() 等。
何时使用“视图”与“副本”
视图:节省内存,不需要数据独立时适用,例如在切片数组时,避免创建额外数据。
副本:适用于需要独立数据、不会影响原数组的场景,如在独立的数据处理或分析时。
5.reshape() 中的 order 参数
reshape() 中的 order 参数控制重塑顺序:
C:按行重塑(默认)F:按列重塑A:根据内存中的数组布局选择
示例:
# 按列重塑为 3x2 数组
reshaped_f_order = arr.reshape(3, 2, order='F')
print(reshaped_f_order)
# 输出:
# [[1 4]
# [2 5]
# [3 6]]
6.总结
方法描述示例用法reshape(new_shape)将数组重塑为指定形状,新形状的元素总数必须等于原数组总数。arr.reshape(2, 3)reshape(-1, n)使用 -1 自动推断某个维度,使得总元素数不变。arr.reshape(-1, 3)np.resize(new_shape)更改数组形状,不受元素总数限制。若元素不足,会循环填充;多余元素会被截断。np.resize(arr, (2, 4))ravel()展开为一维数组,返回的是原数组的视图。arr2d.ravel()flatten()展开为一维数组,返回的是原数组的副本。arr2d.flatten()reshape(new_shape, order='C')按行重塑(默认,C 风格);也可用 order='F' 按列重塑或 order='A' 根据内存布局选择。arr.reshape(3, 2, order='F')这些方法让数组变形更加灵活,以适应不同维度和场景的需求。
6.4. 数组的拼接
数组的拼接是指将多个数组沿指定轴连接成一个新的数组。NumPy 提供了多种方法来进行数组的拼接,常见的有 concatenate()、stack()、hstack()、vstack() 和 dstack()。
1. np.concatenate()
concatenate() 可以沿指定的轴拼接多个数组,数组的维度必须一致。
语法:np.concatenate((arr1, arr2, ...), axis=0)参数:axis 指定拼接轴,默认 axis=0(沿行方向)。
示例:
对于一维数组:
import numpy as np
# 创建两个一维数组
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
# 沿行方向拼接
result = np.concatenate((arr1, arr2))
print(result) # 输出: [1 2 3 4 5 6]
#np.concatenate()函数在处理一维数组时,确实不能沿列方向进行拼接,因为一维数组本身没有列的概念。
对于二维数组:
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
# 沿行方向拼接(axis=0)
result = np.concatenate((arr1, arr2), axis=0)
# 输出:
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
# 沿列方向拼接(axis=1)
result = np.concatenate((arr1, arr2), axis=1)
# 输出:
# [[1 2 5 6]
# [3 4 7 8]]
2. np.stack()
stack() 用于沿新轴拼接数组,生成一个新的高维数组。要求数组的形状必须完全相同。
语法:np.stack((arr1, arr2, ...), axis=0)参数:axis 指定新的拼接轴位置,默认 axis=0(沿行方向)。
示例
1.一维数组示例:
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
#axis=0 沿第一个轴(在一维数组中会创建一个二维数组)
result = np.stack((arr1, arr2), axis=0)
print(result)
# 输出:
# [[1 2 3]
# [4 5 6]]
# 形状: (2, 3)
#axis=1 沿第二个轴堆叠(在一维数组中会创建一个二维数组)
result = np.stack((arr1, arr2), axis=1)
print(result)
# 输出:
# [[1 4]
# [2 5]
# [3 6]]
# 形状: (3, 2)
在这里,axis=0 表示 np.stack() 会在最外层创建一个新维度,形成一个二维数组。axis=1 表示 np.stack() 会在第二个轴的位置插入新维度,形成一个二维数组,每个元素被按列堆叠。
2.二维数组的示例
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array([[7, 8, 9], [10, 11, 12]])
#axis=0 沿第一个轴(生成形状为 (2, 2, 3) 的三维数组)
result = np.stack((arr1, arr2), axis=0)
print(result)
# 输出:
# [[[ 1 2 3]
# [ 4 5 6]]
#
# [[ 7 8 9]
# [10 11 12]]]
# 形状: (2, 2, 3)
#axis=1 沿第二个轴(生成形状为 (2, 2, 3) 的三维数组)
result = np.stack((arr1, arr2), axis=1)
print(result)
# 输出:
# [[[ 1 2 3]
# [ 7 8 9]]
#
# [[ 4 5 6]
# [10 11 12]]]
# 形状: (2, 2, 3)
#axis=2 沿第三个轴(生成形状为 (2, 3, 2) 的三维数组)
result = np.stack((arr1, arr2), axis=2)
print(result)
# 输出:
# [[[ 1 7]
# [ 2 8]
# [ 3 9]]
#
# [[ 4 10]
# [ 5 11]
# [ 6 12]]]
# 形状: (2, 3, 2)
在此例中,axis=0 将 arr1 和 arr2 放置在新数组的第一个维度。axis=1 表示在第二个轴的位置插入新维度,使数组沿行方向逐个堆叠。axis=2 将数组沿列方向逐个堆叠,生成了一个新的三维数组。
3. np.hstack() 和 np.vstack()
hstack():沿水平方向(行方向)拼接数组,等价于 concatenate() 中 axis=1 的情况。vstack():沿垂直方向(列方向)拼接数组,等价于 concatenate() 中 axis=0 的情况。
示例:
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
# 水平方向拼接
result1 = np.hstack((arr1, arr2))
print(result1) # 输出: [1 2 3 4 5 6]
# 垂直方向拼接
result2 = np.vstack((arr1, arr2))
print(result2)
# 输出:
#[[1 2 3]
# [4 5 6]]
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
# 水平方向拼接
result3 = np.hstack((arr1, arr2))
print(result3)
# 输出:
#[[1 2 5 6]
# [3 4 7 8]]
# 垂直方向拼接
result4 = np.vstack((arr1, arr2))
print(result4)
# 输出:
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
4. np.dstack()
dstack() 沿深度方向(第三维)拼接数组,适用于二维数组。
示例:
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
result = np.dstack((arr1, arr2))
# 输出:
# [[[1 5]
# [2 6]]
#
# [[3 7]
# [4 8]]]
5. np.column_stack() 和 np.row_stack()
column_stack():将一维数组作为列堆叠成二维数组,或沿列方向拼接二维数组。row_stack():将一维数组作为行堆叠成二维数组。它们主要是为一维和二维数组设计的,尽管在某些情况下它们可以用于三维及更高维数组,但这并不是它们的主要用途。
示例:
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
# 列堆叠
result = np.column_stack((arr1, arr2))
# 输出:
# [[1 4]
# [2 5]
# [3 6]]
# 行堆叠(等同于 vstack)
result = np.row_stack((arr1, arr2))
# 输出:
# [[1 2 3]
# [4 5 6]]
6.总结
方法描述np.concatenate()沿指定轴拼接数组np.stack()沿新的轴拼接数组,生成一个新的高维数组np.hstack()沿水平方向(列)拼接数组np.vstack()沿垂直方向(行)拼接数组np.dstack()沿深度方向(第三维)拼接数组np.column_stack()将一维数组作为列堆叠成二维,或沿列方向拼接np.row_stack()将一维数组作为行堆叠成二维,等同于 vstack()这些方法帮助将数组按不同维度进行拼接,适用于多种数据结构。
6.5. 数组的分裂
数组的分裂(或拆分)是将一个数组分割成多个子数组的过程。NumPy 提供了几种常用的数组分裂方法,主要包括 np.split()、np.array_split()、np.hsplit()、np.vsplit() 和 np.dsplit()。
1.np.split()
split() 将数组沿指定的轴分成相等的部分。如果数组无法均匀分割,会报错。
语法:np.split(arr, indices_or_sections, axis=0)参数:
arr:待分割的数组。indices_or_sections:整数(将数组分成几部分)或整数列表(指定分割的索引位置)。axis:沿哪个轴进行分割,默认为 0(沿行方向)。
示例:
对于一维数组:
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
result = np.split(arr, 3) # 将数组分成 3 份
print(result)
# 输出:
# [array([1, 2]), array([3, 4]), array([5, 6])]
对于二维数组:
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
result = np.split(arr, 2, axis=0) # 沿行分成 2 份
# 输出:
# [array([[ 1, 2, 3],
# [ 4, 5, 6]]),
# array([[ 7, 8, 9],
# [10, 11, 12]])]
2. np.array_split()
array_split() 允许数组在不能均匀分割时,尽量均匀地分成尽可能相等的部分。它适用于任何分割情况。
语法:np.array_split(arr, indices_or_sections, axis=0)
示例:
arr = np.array([1, 2, 3, 4, 5])
result = np.array_split(arr, 3)
print(result)
# 输出:
# [array([1, 2]), array([3, 4]), array([5])]
在二维数组中:
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
result = np.array_split(arr, 2, axis=1) # 沿列方向分成 2 份
# 输出:
# [array([[1, 2],
# [4, 5],
# [7, 8]]),
# array([[3],
# [6],
# [9]])]
3. np.hsplit()
hsplit() 沿水平方向(列)分割数组。适用于至少有两列的数组,相当于 np.split(arr, indices_or_sections, axis=1)。
示例:
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
result = np.hsplit(arr, 2)
print(result)
# 输出:
# [array([[1, 2],
# [5, 6]]),
# array([[3, 4],
# [7, 8]])]
4. np.vsplit()
vsplit() 沿垂直方向(行)分割数组。适用于至少有两行的数组,相当于 np.split(arr, indices_or_sections, axis=0)。
示例:
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
result = np.vsplit(arr, 2)
print(result)
# 输出:
# [array([[1, 2, 3],
# [4, 5, 6]]),
# array([[ 7, 8, 9],
# [10, 11, 12]])]
5. np.dsplit()
dsplit() 用于分割三维数组的第三维(深度),相当于 np.split(arr, indices_or_sections, axis=2)。适用于三维数组。
示例:
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
result = np.dsplit(arr, 3)
print(result)
# 输出:
# [array([[[ 1],
# [ 4]],
#
# [[ 7],
# [10]]]),
# array([[[ 2],
# [ 5]],
#
# [[ 8],
# [11]]]),
# array([[[ 3],
# [ 6]],
#
# [[ 9],
# [12]]])]
6.总结
函数描述np.split()沿指定轴均匀分割数组,不能均分时报错np.array_split()沿指定轴分割数组,允许不均匀分割np.hsplit()沿水平方向分割数组(仅适用于二维及以上数组)np.vsplit()沿垂直方向分割数组(仅适用于二维及以上数组)np.dsplit()沿第三维分割三维数组这些分割方法有助于将数组按不同需求拆分,用于处理和分析大型多维数据。
6.6、总结
变形操作描述函数/方法转置交换维度transpose(), T, swapaxes()翻转沿指定轴翻转flip(), flipud(), fliplr()重塑改变形状reshape(), ravel(), flatten()拼接连接数组concatenate(), stack(), vstack(), hstack()分裂拆分数组split(), hsplit(), vsplit()这些变形操作帮助在数据处理中更灵活地操作数组结构,适应不同计算场景的需求。
7、布尔型数组
布尔型数组是一种只包含布尔值 (True 或 False) 的数组,常用于筛选、条件判断和数据分析。在 NumPy 中,布尔型数组的创建和操作是非常灵活和高效的。
7.1.创建布尔型数组
在 NumPy 中,可以通过多种方式创建布尔型数组,以下是常用方法:
1.使用条件表达式创建布尔数组
将条件表达式应用于 NumPy 数组,可以返回一个布尔型数组。
import numpy as np
# 示例数组
arr = np.array([1, 2, 3, 4, 5])
# 通过条件表达式生成布尔数组
bool_arr = arr > 3
print(bool_arr) # 输出: [False False False True True]
2.直接创建布尔数组
可以使用 np.array() 来直接创建布尔数组:
bool_arr = np.array([True, False, True])
print(bool_arr) # 输出: [ True False True]
3.使用逻辑运算符生成布尔数组
对数组进行逻辑运算(如 &, |, ~)会生成布尔数组。
arr1 = np.array([True, False, True])
arr2 = np.array([False, True, True])
result = arr1 & arr2 # 逻辑与运算
print(result) # 输出: [False False True]
4.使用 np.full() 创建指定形状的布尔数组
可以使用 np.full() 创建全 True 或全 False 的布尔数组。
# 创建形状为 (2, 3) 的布尔数组,全为 True
bool_arr = np.full((2, 3), True)
print(bool_arr)
# 输出:
# [[ True True True]
# [ True True True]]
语法解释:
np.full(shape, fill_value, dtype=None, order='C')
shape:数组的形状,以元组形式指定。如 (2, 3) 表示 2 行 3 列的数组。
fill_value:填充数组的值。可以是整数、浮点数或布尔值。
dtype(可选):数组的数据类型,默认为 None,即由 fill_value 自动推断。
order(可选):数组的存储顺序,‘C’ 表示行优先(C 风格),‘F’ 表示列优先(Fortran 风格)。默认值为 ‘C’。
5.使用 np.ones() 或 np.zeros() 并指定 dtype=bool
也可以通过 np.ones() 或 np.zeros() 创建布尔数组。
# 创建全为 True 的布尔数组
true_arr = np.ones((2, 3), dtype=bool)
print(true_arr)
# 创建全为 False 的布尔数组
false_arr = np.zeros((2, 3), dtype=bool)
print(false_arr)
6.使用 np.random.choice() 随机生成布尔数组
np.random.choice() 可以用来随机生成布尔值。
bool_arr = np.random.choice([True, False], size=(3, 3))
print(bool_arr)
语法解释:
np.random.choice(a, size=None, replace=True, p=None)
a:可以是数组或整数。如果是数组,则从中随机选择元素;如果是整数 n,则视为 np.arange(n)。size(可选):输出数组的形状。如果为 None,则返回单个随机选择的元素;如果为整数或元组,表示所需的输出形状。replace(可选):是否允许重复选择,默认值为 True(允许重复)。如果设为 False,则为不重复抽样。p(可选):每个元素被选中的概率分布,必须与 a 的长度相同,并且总和为 1。默认情况下,均匀分布(即所有元素被选中的概率相同)。
这些方法提供了灵活的方式来生成布尔型数组,在数据筛选和逻辑判断中非常有用。
7.2布尔数组的常见操作
计数 True 值:np.sum() 可以统计布尔数组中 True 的个数。
bool_arr = np.array([True, False, True, True])
count = np.sum(bool_arr)
print(count) # 输出: 3
判断全真或全假:
np.all():如果布尔数组中的所有值都为 True,返回 True,否则返回 False。
np.any():如果布尔数组中有一个值为 True,返回 True,否则返回 False。
bool_arr = np.array([True, False, True])
print(np.all(bool_arr)) # 输出: False
print(np.any(bool_arr)) # 输出: True
反转布尔值:~ 运算符可以反转布尔数组中的值。
bool_arr = np.array([True, False, True])
print(~bool_arr) # 输出: [False True False]
筛选特定条件下的元素
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
bool_arr = arr > 4
filtered_arr = arr[bool_arr]
print(filtered_arr) # 输出: [5 6 7 8 9]