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_arr1
和py_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数组的属性,调用诸如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.]]
创建随机数数组
您还可以创建具有特定形状的数组,并用从特定分布中抽取的随机数填充。常用的概率分布有均匀分布和标准正态分布。
可以使用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)
分别找到最大和最小元素的索引。了解更多关于NumPyargmax()
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))
由于堆叠是水平进行的,输入数组应该有相同的行数。在这里,arr1
和arr2
都有三行。
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。