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 // a |
4.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()
检查是否大于 <
np.less()
检查是否小于 >=
np.greater_equal()
检查是否大于等于 <=
np.less_equal()
检查是否小于等于 -
示例代码
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.T |
swapaxes() | 二维或多维数组 | 交换指定的两个轴,适合高维数组中单独交换两维的情况 | 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]