NumPy 数组:简介 [带例子]

想要开始使用NumPy吗?本指南将教你如何在Python中使用NumPy数组的基础知识。

作为第一步,你将学习NumPy数组与Python列表的不同之处。然后,你将学习几种创建NumPy数组并对它们进行基本操作的方法。

让我们开始吧!

NumPy数组的基础知识

NumPy是最受欢迎的用于科学计算和数据分析的Python库之一。NumPy的基本数据结构是N维数组(N-D数组)。它们具有广播能力,使我们能够对操作进行向量化以提高速度,并使用内置的数学函数来提高性能。

要开始使用NumPy,你首先应该安装该库并将其导入到你的工作环境中。它可以作为一个可通过pip安装的PyPI package获得。

要安装NumPy,请打开终端并运行以下命令:

pip3 install numpy

安装完NumPy后,你可以将其导入到你的工作环境中,并给它一个别名。通常的别名是np

import numpy as np

注意:将NumPy导入为别名np不是必需的,但这是一个推荐的惯例。

Python列表 vs. 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)
 in 
----> 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)

以下是输出,一个零的2D数组:

[[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.]]

创建随机数数组

您还可以创建具有特定形状的数组,并用从特定分布中抽取的随机数填充。常用的概率分布有均匀分布和标准正态分布。

可以使用NumPy的random模块中的randn()函数生成从标准正态分布中抽样的数字数组。标准正态分布是均值为零,方差为一的高斯分布。

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的random模块中的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()函数返回一个在start和stop值之间以step值为步长的数字数组:start,start + step,start + 2*step直到但不包括stop。start和step值是可选的。默认步长为1,起始值为0。

在此示例中,array_a是一个从1开始,步长为0.5,但不包括10的数字数组。

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的random模块的函数创建数组时,每次运行代码都会得到不同的结果。为了获取可重现的结果,我们应该设置一个种子:np.random.seed(seed_value)。

在以下示例中,我设置了可重现性的种子,int_arr1是一个包含7个在区间[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()方法。

在这里,最大元素73出现在索引2处。

int_arr1.argmax()
# 2

最小元素20出现在索引0处。

int_arr1.argmin()
# 0

你还可以使用np.argmax(array)np.argmin(array)分别找到最大和最小元素的索引。了解更多关于NumPy argmax() function的内容。

如何连接NumPy数组

另一个你可能想要使用NumPy数组来完成的常见操作是连接。

使用vstack进行垂直连接

你可以使用vstack()函数来垂直连接数组。

这是一个例子。arr1是一个具有两行三列的全为1的数组,arr2是一个具有两行三列的全为0的数组。

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)
 in 
----> 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

你还可以使用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维数组在速度和效率方面的优势。

您还学习了几个有用的函数来创建特定维度的数组并执行常见操作,例如查找最小和最大元素、连接数组等等。

接下来,学习如何reshape NumPy arrays

类似文章