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_arr1py_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)。 在本节中,我们将学习如何使用其中一些内置函数。

如何创建 NumPy 数组

创建零和一的数组

创建一个由全零或全一填充的特定维度数组通常很有帮助。 然后在程序的后续步骤中使用和修改它们。

我们可以使用zeros()函数来创建一个零数组。 将所需数组的形状作为元组传递: np.zeros(shape)

 array0 = np.zeros((3,3)) print(array0)

这是输出,一个二维零数组:

 [[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]]

您可以访问 NumPy 数组的属性,调用dtypeshape等属性,使用点符号,如下所示:

 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返回startstop值之间的数字数组: startstart + stepstart + 2*step up to but not including stopstartstep值是可选的。 默认步长为 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)获取startstop值之间均匀分布的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)分别查找最大和最小元素的索引。 了解有关 NumPy argmax()函数的更多信息。

如何连接 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))

因为堆叠是水平进行的,所以输入数组的数应该相同。 这里, arr1arr2都有三行。

 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 数组。