NumPy 数组:简介 [含示例]
已发表: 2022-12-08想要开始使用 NumPy? 本指南将教您 Python 中 NumPy 数组的基础知识。
作为第一步,您将了解 NumPy 数组与 Python 列表的工作方式有何不同。 然后,您将学习几种创建 NumPy 数组并对它们执行基本操作的方法。
让我们开始!
NumPy 数组基础知识
NumPy 是用于科学计算和数据分析的最流行的 Python 库之一。 NumPy 中的基本数据结构是 N 维数组(ND 数组)。 它们具有广播功能,允许我们对操作进行矢量化以提高速度,并使用内置的数学函数来提高性能。
要开始使用 NumPy,您应该首先安装该库并将其导入您的工作环境。 它作为可通过 pip 安装的 PyPI 包提供。
要安装 NumPy,请打开终端并运行以下命令:
pip3 install numpy
安装 NumPy 后,您可以使用别名将其导入到您的工作环境中。 通常的别名是np
。
import numpy as np
注意:在别名
np
下导入 NumPy 不是必需的,而是推荐的约定。
Python 列表与 NumPy 数组
考虑以下 Python 数字列表:
py_list = [1,2,3,4]
您可以通过以列表作为参数调用np.array()
函数,从现有列表中获取 NumPy 数组。
np_arr1 = np.array(py_list) print(np_arr1) [1 2 3 4]
要检查np_arr1
的类型,您可以调用内置的type()
函数,您会看到它是ndarray
,这是 NumPy 中的基本数据结构。
type(np_arr1) # numpy.ndarray
尽管 Python 列表和 NumPy 数组看起来很相似,但还是有一些区别:
- Python 列表可以包含不同数据类型的对象,而 NumPy 数组包含相同数据类型的元素。 默认数据类型为精度为 64 位的浮点数 (float64)。
- Python 列表的元素不一定存储在内存中的连续位置。 但是,NumPy 数组的元素存储在内存中的连续块中。 因此,查找和访问元素的速度更快。
让我们回顾一下其他几个差异。
广播
NumPy 数组的一个强大功能是广播。 假设我们想将 2 添加到np_arr1
和py_list
的所有元素。
让我们尝试将 2 添加到py_list
,看看会发生什么:
>>> py_list + 2
我们看到我们得到一个 TypeError,说明我们只能连接两个列表,并且不支持像这样添加 py_list + 2。
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-5-c0f9974899df> in <module> ----> 1 py_list + 2 TypeError: can only concatenate list (not "int") to list
让我们在数组np_arr1
上尝试相同的操作。
>>> np_arr1 + 2
在结果中,我们看到数组的每个元素都添加了 2。
array([3, 4, 5, 6])
这是因为 NumPy 将标量 2 隐式广播到兼容形状的数组以产生此结果。
矢量化
NumPy 数组支持矢量化以实现更快的元素操作。 假设我们想要找到两个数组的逐元素总和。
在列表上使用简单的+
操作将返回两个列表的串联(这不是我们想要的!)。
>>> py_list + py_list # [1, 2, 3, 4, 1, 2, 3, 4]
但是对 NumPy 数组np_arr1
的相同操作返回np_arr1
与自身的逐元素总和。
>>> np_arr1 + np_arr1 # array([2, 4, 6, 8])
同样,嵌套列表在结构上可能类似于 N 维 NumPy 数组。 但是,到目前为止讨论的差异仍然存在。
nested_list = [[1,2],[3,4],[5,6]] np_arr2 = np.array(nested_list) print(np_arr2)
[[1 2] [3 4] [5 6]]
如何创建 NumPy 数组
您始终可以使用np.array(list-obj)
从现有的 Python 列表创建 NumPy 数组。 但是,这不是最有效的方法。
相反,您可以使用多个内置函数来创建特定形状的数组。 数组的形状是一个元组,表示数组沿每个维度的大小。 例如,两行两列的 2×2 数组的形状是 (2,2)。 在本节中,我们将学习如何使用其中一些内置函数。
创建零和一的数组
创建一个由全零或全一填充的特定维度数组通常很有帮助。 然后在程序的后续步骤中使用和修改它们。
我们可以使用zeros()
函数来创建一个零数组。 将所需数组的形状作为元组传递: np.zeros(shape)
。
array0 = np.zeros((3,3)) print(array0)
这是输出,一个二维零数组:
[[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]]
您可以访问 NumPy 数组的属性,调用dtype
和shape
等属性,使用点符号,如下所示:
print(array0.dtype) # float64 print(array0.shape) # (3, 3)
要获得一个数组,您可以使用np.ones()
函数。
array1 = np.ones((3,3)) print(array1)
[[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]]
创建单位矩阵
单位矩阵广泛用于线性代数的多种应用中。 您可以使用np.eye()
函数创建单位矩阵。 np.eye()
函数只接受一个参数:矩阵的顺序 ( n
)。
arrayi = np.eye(3) print(arrayi)
[[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]]
创建随机数数组
您还可以创建特定形状的数组,其中填充了从特定分布中抽取的随机数。 常用的概率分布有均匀分布和标准正态分布。
randn()
函数是 NumPy random
模块的一部分,可用于生成从标准正态分布中采样的数字数组。 标准正态分布是具有零均值和单位方差的高斯分布。
std_arr = np.random.randn(3,4) print(std_arr)
[[-0.13604072 1.21884359 2.06850932 0.78212093] [ 0.44314719 -0.78084801 -0.70517138 1.17984949] [ 1.13214829 1.02339351 0.15317809 1.83191128]]
np.random.rand()
返回区间 [0,1) 内均匀分布的数字样本数组。
uniform_arr = np.random.rand(2,3) print(uniform_arr)
[[0.90470384 0.18877441 0.10021817] [0.741 0.10657658 0.71334643]]
您还可以使用 NumPy 随机模块中的randint()
函数创建一个随机整数数组。 np.random.randint(low, high, size)
返回一个整数数组。 数组的形状是从size
参数推断出来的,整数取区间[low,high)
中的值。
这是一个例子:
int_arr = np.random.randint(1,100,(2,3)) print(int_arr)
[[53 89 33] [24 85 33]]
其他有用的内置函数
接下来,让我们了解一些其他有用的函数来创建 NumPy 数组。
arange()
函数以步长值的step
返回start
和stop
值之间的数字数组: start
、 start + step
、 start + 2*step
up to but not including stop
。 start
和step
值是可选的。 默认步长为 1,默认起始值为 0。
在此示例中, array_a
是一个数字数组,从 1 开始,但不包括 10,步长为 0.5。
array_a = np.arange(1,10,0.5) print(array_a)
[1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8. 8.5 9. 9.5]
您还可以使用np.linspace()
创建间隔均匀的数字数组。 使用np.linspace(start, stop, num)
获取start
和stop
值之间均匀分布的num
个数字的数组。
这里, arr_lin
是区间 [1,10] 中 5 个均匀分布的数字的数组。
array_lin = np.linspace(1,10,5) print(array_lin)
[ 1. 3.25 5.5 7.75 10. ]
同理, arr_lin2
是区间 [1,20] 中 10 个等距数字的数组。
array_lin2 = np.linspace(1,20,10) print(array_lin2)
[ 1. 3.11111111 5.22222222 7.33333333 9.44444444 11.55555556 13.66666667 15.77777778 17.88888889 20. ]
与arange()
函数不同, linspace()
函数默认包含端点。
NumPy 数组的基本操作
接下来,让我们回顾一下 NumPy 数组的一些基本操作。
寻找最小和最大元素
每当我们使用 NumPy 的随机模块中的函数来创建数组时,每次运行代码时我们都会得到不同的结果。 为了获得可重现的结果,我们应该设置一个种子: np.random.seed(seed_value)
。
在下面的示例中,我设置了可重复性的种子, int_arr1
是区间 [1,100) 中七个随机整数的数组。
np.random.seed(27) int_arr1 = np.random.randint(1,100,7) print(int_arr1) # [20 57 73 32 57 38 25]
- 要找到数组中的最大元素,可以调用数组对象
int_arr1
上的max()
方法,然后 - 要找到数组中的最小元素,可以调用数组对象
int_arr1
上的min()
方法。
int_arr1.max() # 73 int_arr1.min() # 20
查找最大和最小元素的索引
有时,您可能需要找到最大和最小元素的索引。 为此,您可以调用数组对象的argmax()
和 argmin( argmin()
方法。
这里,最大元素 73 出现在索引 2 处。
int_arr1.argmax() # 2
最小元素 20 出现在索引 0 处。
int_arr1.argmin() # 0
您还可以使用
np.argmax(array)
和np.argmin(array)
分别查找最大和最小元素的索引。 了解有关 NumPyargmax()
函数的更多信息。
如何连接 NumPy 数组
您可能希望对 NumPy 数组执行的另一个常见操作是串联。
使用 vstack 的垂直串联
您可以使用vstack()
函数垂直连接数组。
这是一个例子。 arr1
是一个两行三列的数组, arr2
是两行三列的零数组。
arr1 = np.ones((2,3)) arr2 = np.zeros((2,3))
我们可以使用vstack()
函数垂直连接这两个数组,如下所示:
np.vstack((arr1,arr2))
array([[1., 1., 1.], [1., 1., 1.], [0., 0., 0.], [0., 0., 0.]])
由于堆叠是垂直发生的,因此两个数组的列数应该相同。
让我们将arr2
的形状更改为 (2,2)。 它现在有两行和两列。
arr1 = np.ones((2,3)) arr2 = np.zeros((2,2)) np.vstack((arr1,arr2))
因此,垂直连接是不可能的,我们得到一个 ValueError。
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-21-d5d3bf37fc21> in <module> ----> 1 np.vstack((arr1,arr2)) ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 3 and the array at index 1 has size 2
使用 hstack 的水平连接
您可以使用hstack()
函数水平连接 NumPy 数组,如下所示。
arr1 = np.ones((3,3)) arr2 = np.zeros((3,2))
np.hstack((arr1,arr2))
因为堆叠是水平进行的,所以输入数组的行数应该相同。 这里, arr1
和arr2
都有三行。
array([[1., 1., 1., 0., 0.], [1., 1., 1., 0., 0.], [1., 1., 1., 0., 0.]])
使用连接
您还可以使用concatenate()
函数沿特定轴连接 NumPy 数组。 将可选的axis
参数设置为您想要连接的轴; 轴的默认值为零。
这里有一些例子:
arr1 = np.ones((2,3)) arr2 = np.zeros((2,3))
当我们没有指定要连接的轴时,数组将沿着轴 0 连接。在结果数组中,第二个数组arr2
添加(作为行)在第一个数组下面。
np.concatenate((arr1,arr2))
array([[1., 1., 1.], [1., 1., 1.], [0., 0., 0.], [0., 0., 0.]])
当我们指定axis = 1
时,我们得到以下结果。 arr2
连接(作为列)在第一个数组arr1
旁边。
np.concatenate((arr1,arr2),axis=1)
array([[1., 1., 1., 0., 0., 0.], [1., 1., 1., 0., 0., 0.]])
与hstack()
和vstack()
函数一样,数组沿连接轴的维度应该匹配。
结论
在本教程中,您了解了 NumPy 数组和 Python 列表之间的区别,重点介绍了 N 维数组在速度和效率方面的优势。
您还学习了几个有用的函数来创建特定维度的数组并执行常见操作,例如查找最小和最大元素、连接数组等。
接下来,学习如何重塑 NumPy 数组。