NumPy 1.26 中文官方指南(二)(2)https://developer.aliyun.com/article/1510606
阅读示例代码
如果你还不熟悉阅读包含大量代码的教程,你可能不知道如何解释像这样的代码块:
>>> a = np.arange(6) >>> a2 = a[np.newaxis, :] >>> a2.shape (1, 6)
如果你不熟悉这种风格,那么很容易理解。如果你看到>>>
,你正在看输入,或者你将要输入的代码。任何不以>>>
开头的都是输出,或者是你代码运行的结果。这是在命令行上运行python
时看到的样式,但如果你使用 IPython,你可能会看到不同的样式。请注意,它不是代码的一部分,如果输入或粘贴到 Python shell 中会导致错误。它可以安全地输入或粘贴到 IPython shell 中;>>>
会被忽略。
Python 列表和 NumPy 数组之间有什么区别?
NumPy 为您提供了大量快速高效的方式来创建数组并在其中操纵数字数据。 虽然 Python 列表可以包含单个列表中的不同数据类型,但 NumPy 数组中的所有元素应该是同质的。 如果数组不是同质的,那么对数组执行的数学运算将非常低效。
为什么使用 NumPy?
NumPy 数组比 Python 列表更快,更紧凑。 数组占用的内存更少且使用方便。 NumPy 使用的内存比存储数据需要的内存少得多,并提供了指定数据类型的机制。 这进一步优化了代码。
什么是数组?
数组是 NumPy 库的核心数据结构。 数组是一组值的网格,它包含有关原始数据的信息,如何定位元素以及如何解释元素。 它有一组可以以各种方式进行索引的元素。 这些元素都是相同类型的,称为数组的dtype
。
数组可以通过非负整数元组、布尔值、另一个数组或整数进行索引。 数组的rank
是维数。 数组的shape
是一组整数,给出沿每个维度的数组大小。
我们可以从 Python 列表中初始化 NumPy 数组的一种方式是使用嵌套列表进行二维或多维数据。
例如:
>>> a = np.array([1, 2, 3, 4, 5, 6])
或者:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
我们可以使用方括号访问数组中的元素。 当访问元素时,要记住 NumPy 中的索引从 0 开始。 这意味着如果您要访问数组中的第一个元素,您将访问元素“0”。
>>> print(a[0]) [1 2 3 4]
有关数组的更多信息
本部分涵盖 1D array
, 2D array
, ndarray
, vector
, matrix
你可能偶尔会听到一个数组被称为ndarray
,这是“N-dimensional array”的简称。 N 维数组只是具有任意数量维度的数组。 您还可能听说1-D或一维数组,2-D或二维数组等。 NumPy ndarray
类用于表示矩阵和向量。 向量是具有单个维度的数组(行向量和列向量之间没有区别),而矩阵指的是具有两个维度的数组。 对于3-D或更高维数组,术语张量也常常使用。
数组的属性是什么?
数组通常是相同类型和大小的项目的固定大小容器。 数组中的维数和项目数由其形状定义。数组的形状是一组非负整数元组,用于指定每个维度的大小。
在 NumPy 中,维度被称为轴。 这意味着如果你有一个看起来像这样的二维数组:
[[0., 0., 0.], [1., 1., 1.]]
你的数组有 2 个轴。 第一个轴的长度为 2,第二个轴的长度为 3。
就像其他 Python 容器对象一样,数组的内容可以通过对数组进行索引或切片来访问和修改。与典型的容器对象不同,不同的数组可以共享相同的数据,因此在一个数组上进行的更改可能会在另一个数组中可见。
数组的属性反映了数组本身的内在信息。如果你需要获取或设置数组的属性而不创建新数组,通常可以通过其属性访问数组。
在这里阅读有关数组属性的更多信息,并了解数组对象。
如何创建基本数组
这一部分涵盖了np.array()
,np.zeros()
,np.ones()
,np.empty()
,np.arange()
,np.linspace()
,dtype
要创建一个 NumPy 数组,您可以使用函数np.array()
。
要创建一个简单的数组,您只需要将列表传递给它。如果您选择的话,还可以指定列表中的数据类型。您可以在这里找到有关数据类型的更多信息。
>>> import numpy as np >>> a = np.array([1, 2, 3])
您可以以此方式可视化您的数组:
请注意,这些可视化是为了简化思想并让您对 NumPy 概念和机制有基本了解。数组和数组操作比这里描述的要复杂得多!
除了从一系列元素创建数组之外,您还可以轻松创建一个填满0
的数组:
>>> np.zeros(2) array([0., 0.])
或者一个填满1
的数组:
>>> np.ones(2) array([1., 1.])
或者甚至是一个空数组!函数empty
创建一个初始内容是随机的数组,取决于内存状态。使用empty
而不是zeros
(或类似的东西)的原因是速度快 - 只需确保之后填充每个元素!
>>> # Create an empty array with 2 elements >>> np.empty(2) array([3.14, 42\. ]) # may vary
您可以创建一个包含一系列元素的数组:
>>> np.arange(4) array([0, 1, 2, 3])
甚至包含一系列间隔均匀的范围的数组。为此,您将指定第一个数字,最后一个数字和步长。
>>> np.arange(2, 9, 2) array([2, 4, 6, 8])
您还可以使用np.linspace()
在指定间隔中创建线性间隔的值数组:
>>> np.linspace(0, 10, num=5) array([ 0\. , 2.5, 5\. , 7.5, 10\. ])
指定数据类型
尽管默认数据类型是浮点数(np.float64
),但您可以使用dtype
关键字明确指定您想要的数据类型。
>>> x = np.ones(2, dtype=np.int64) >>> x array([1, 1])
在这里了解更多有关创建数组的信息
添加、删除和排序元素
这一部分涵盖了np.sort()
,np.concatenate()
使用np.sort()
对元素进行排序很简单。在调用该函数时,您可以指定轴、种类和顺序。
如果您从这个数组开始:
>>> arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
您可以快速将数字按升序排序为:
>>> np.sort(arr) array([1, 2, 3, 4, 5, 6, 7, 8])
除了返回一个排序后的数组副本的 sort 之外,您还可以使用:
argsort
,它是沿指定轴的间接排序,lexsort
,这是多个键的间接稳定排序,searchsorted
,将在排序数组中查找元素,并partition
,这是一种部分排序。
要阅读有关对数组排序的更多信息,请参阅:sort
.
如果你从这些数组开始:
>>> a = np.array([1, 2, 3, 4]) >>> b = np.array([5, 6, 7, 8])
您可以使用np.concatenate()
进行连接。
>>> np.concatenate((a, b)) array([1, 2, 3, 4, 5, 6, 7, 8])
或者,如果你从这些数组开始:
>>> x = np.array([[1, 2], [3, 4]]) >>> y = np.array([[5, 6]])
您可以使用以下内容进行连接:
>>> np.concatenate((x, y), axis=0) array([[1, 2], [3, 4], [5, 6]])
为了从数组中移除元素,可以简单地使用索引来选择要保留的元素。
要阅读有关连接的更多信息,请参阅:concatenate
.
你如何知道数组的形状和大小?
本节介绍 ndarray.ndim
,ndarray.size
,ndarray.shape
ndarray.ndim
将告诉您数组的轴数或维度。
ndarray.size
将告诉您数组的元素总数。这是数组形状元素的乘积。
ndarray.shape
将显示一个元组,其中的整数指示数组沿每个维度存储的元素数。例如,如果你有一个 2 行 3 列的二维数组,你的数组的形状是(2, 3)
。
例如,如果你创建了这个数组:
>>> array_example = np.array([[[0, 1, 2, 3], ... [4, 5, 6, 7]], ... ... [[0, 1, 2, 3], ... [4, 5, 6, 7]], ... ... [[0 ,1 ,2, 3], ... [4, 5, 6, 7]]])
要找到数组的维数,运行:
>>> array_example.ndim 3
要找到数组中的总元素数,请运行:
>>> array_example.size 24
并找到数组的形状,运行:
>>> array_example.shape (3, 2, 4)
你能重塑一个数组吗?
本节介绍 arr.reshape()
是的!
使用arr.reshape()
将为数组提供新的形状,而不更改数据。只需记住,当您使用 reshape 方法时,您想要产生的数组的元素数需要与原始数组相同。如果您从一个具有 12 个元素的数组开始,您需要确保您的新数组也总共具有 12 个元素。
如果您从这个数组开始:
>>> a = np.arange(6) >>> print(a) [0 1 2 3 4 5]
您可以使用reshape()
来重塑您的数组。例如,您可以将此数组重塑为具有三行两列的数组:
>>> b = a.reshape(3, 2) >>> print(b) [[0 1] [2 3] [4 5]]
使用np.reshape
,您可以指定一些可选参数:
>>> np.reshape(a, newshape=(1, 6), order='C') array([[0, 1, 2, 3, 4, 5]])
a
是要重塑的数组。
newshape
是你想要的新形状。您可以指定一个整数或一个整数元组。如果您指定一个整数,结果将是一个具有该长度的数组。形状应与原始形状兼容。
order:
C
表示使用类似 C 的索引顺序读取/写入元素,F
表示使用类似 Fortran 的索引顺序读取/写入元素,A
表示如果 a 在内存中是 Fortran 连续的,使用类似 Fortran 的索引顺序读取/写入元素,否则使用类似 C 的顺序。(这是一个可选参数,无需指定。)
如果你想了解有关 C 和 Fortran 排序的更多信息,你可以在这里读取有关 NumPy 数组内存中的内部组织的更多信息。基本上,C 和 Fortran 排序与索引与数组在内存中存储的顺序相对应有关。在 Fortran 中,当在内存中移动二维数组的元素时,第一个索引是最快变化的索引。随着第一个索引的变化移动到下一行,矩阵按列存储。这就是为什么 Fortran 被认为是一种列主语言。另一方面,在 C 中,最后的索引变化最快。矩阵按行存储,使其成为一种行主语言。你在 C 或 Fortran 中所做的取决于是更重要保留索引约定还是不重新排序数据。
在这里了解更多有关形状操作的信息。
如何将一个 1 维数组转换为 2 维数组(如何向数组添加一个新轴)
本节介绍 np.newaxis
,np.expand_dims
你可以使用 np.newaxis
和 np.expand_dims
来增加现有数组的维度。
当使用一次 np.newaxis
时,它会将数组的维度增加一个维度。这意味着一个1D数组将变成一个2D数组,一个2D数组将变成一个3D数组,依此类推。
例如,如果你从这个数组开始:
>>> a = np.array([1, 2, 3, 4, 5, 6]) >>> a.shape (6,)
你可以使用 np.newaxis
来增加一个新的轴:
>>> a2 = a[np.newaxis, :] >>> a2.shape (1, 6)
你可以使用 np.newaxis
将 1 维数组显式地转换为行向量或列向量。例如,你可以通过在第一维度上插入一个轴将 1 维数组转换为行向量:
>>> row_vector = a[np.newaxis, :] >>> row_vector.shape (1, 6)
或者,对于列向量,你可以在第二个维度上插入一个轴:
>>> col_vector = a[:, np.newaxis] >>> col_vector.shape (6, 1)
你还可以使用 np.expand_dims
在指定位置插入一个新的轴,以扩展数组。
例如,如果你从这个数组开始:
>>> a = np.array([1, 2, 3, 4, 5, 6]) >>> a.shape (6,)
你可以使用 np.expand_dims
在索引位置 1 处添加一个轴:
>>> b = np.expand_dims(a, axis=1) >>> b.shape (6, 1)
你可以在索引位置 0 处添加一个轴:
>>> c = np.expand_dims(a, axis=0) >>> c.shape (1, 6)
在这里了解更多有关 newaxis 的信息,以及 expand_dims
。
索引和切片
你可以像切片 Python 列表一样索引和切片 NumPy 数组。
>>> data = np.array([1, 2, 3]) >>> data[1] 2 >>> data[0:2] array([1, 2]) >>> data[1:] array([2, 3]) >>> data[-2:] array([2, 3])
可以这样可视化它:
你可能想从数组中选择一部分或特定的数组元素,用于进一步分析或进行其他操作。为了做到这一点,你需要子集、切片和/或索引你的数组。
如果你想要选择满足特定条件的数组值,使用 NumPy 是非常简单的。
例如,如果你从这个数组开始:
>>> a = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
你可以轻松打印出数组中所有小于 5 的值。
>>> print(a[a < 5]) [1 2 3 4]
你也可以选择大于或等于 5 的数字,并使用该条件来索引数组。
>>> five_up = (a >= 5) >>> print(a[five_up]) [ 5 6 7 8 9 10 11 12]
您可以选择可被 2 整除的元素:
>>> divisible_by_2 = a[a%2==0] >>> print(divisible_by_2) [ 2 4 6 8 10 12]
或者你可以使用&
和|
操作符选取满足两个条件的元素:
>>> c = a[(a > 2) & (a < 11)] >>> print(c) [ 3 4 5 6 7 8 9 10]
您还可以使用逻辑运算符**&和|**返回指定数组中的值是否满足某个条件的布尔值。这对包含名称或其他分类值的数组很有用。
>>> five_up = (a > 5) | (a == 5) >>> print(five_up) [[False False False False] [ True True True True] [ True True True True]]
您还可以使用np.nonzero()
从数组中选择元素或索引。
从这个数组开始:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
您可以使用np.nonzero()
打印出,例如,小于 5 的元素的索引:
>>> b = np.nonzero(a < 5) >>> print(b) (array([0, 0, 0, 0]), array([0, 1, 2, 3]))
在这个例子中,返回了一个数组的元组:每个维度一个。第一个数组表示找到这些值的行索引,第二个数组表示找到值的列索引。
如果您想生成元素存在的坐标列表,可以对数组进行压缩,遍历坐标列表并打印它们。例如:
>>> list_of_coordinates= list(zip(b[0], b[1])) >>> for coord in list_of_coordinates: ... print(coord) (0, 0) (0, 1) (0, 2) (0, 3)
你也可以使用np.nonzero()
打印出数组中小于 5 的元素:
>>> print(a[b]) [1 2 3 4]
如果你要查找的元素在数组中不存在,那么返回的索引数组将是空的。例如:
>>> not_there = np.nonzero(a == 42) >>> print(not_there) (array([], dtype=int64), array([], dtype=int64))
在这里了解有关索引和切片的更多信息和这里。
在此处阅读关于使用零函数的更多信息:nonzero
。
如何从现有数据创建数组
本节涵盖 切片和索引
,np.vstack()
,np.hstack()
,np.hsplit()
,.view()
,copy()
您可以轻松地从现有数组的部分创建新数组。
假设你有这样一个数组:
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
您可以随时使用切片指定要从数组中切片的位置创建数组的新数组。
>>> arr1 = a[3:8] >>> arr1 array([4, 5, 6, 7, 8])
在这里,你从索引位置 3 到索引位置 8 获取了你数组的一个部分。
你也可以垂直和水平地堆叠两个现有数组。假设你有两个数组,a1
和a2
:
>>> a1 = np.array([[1, 1], ... [2, 2]]) >>> a2 = np.array([[3, 3], ... [4, 4]])
你可以使用vstack
将它们垂直堆叠:
>>> np.vstack((a1, a2)) array([[1, 1], [2, 2], [3, 3], [4, 4]])
或者使用hstack
水平堆叠它们:
>>> np.hstack((a1, a2)) array([[1, 1, 3, 3], [2, 2, 4, 4]])
你可以使用hsplit
将数组分割成几个较小的数组。你可以指定要返回的形状相等的数组的数量,或者应该在哪个列之后进行分割。
假设你有这样一个数组:
>>> x = np.arange(1, 25).reshape(2, 12) >>> x array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]])
如果你想将此数组分割成三个形状相等的数组,你需要执行:
>>> np.hsplit(x, 3) [array([[ 1, 2, 3, 4], [13, 14, 15, 16]]), array([[ 5, 6, 7, 8], [17, 18, 19, 20]]), array([[ 9, 10, 11, 12], [21, 22, 23, 24]])]
如果您想在第三和第四列之后分割数组,您需要执行:
>>> np.hsplit(x, (3, 4)) [array([[ 1, 2, 3], [13, 14, 15]]), array([[ 4], [16]]), array([[ 5, 6, 7, 8, 9, 10, 11, 12], [17, 18, 19, 20, 21, 22, 23, 24]])]
在这里了解有关堆叠和分割数组的更多信息。
您可以使用view
方法创建一个查看原始数组相同数据的新数组对象(浅复制)。
视图是一个重要的 NumPy 概念!NumPy 函数以及索引和切片等操作将尽可能返回视图。这样可以节省内存并提高速度(不需要进行数据复制)。但是要注意这一点——修改视图中的数据也会修改原始数组!
假设您创建了这个数组:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
现在我们通过对a
进行切片并修改b1
的第一个元素来创建数组b1
。这将同时修改a
中对应的元素!
>>> b1 = a[0, :] >>> b1 array([1, 2, 3, 4]) >>> b1[0] = 99 >>> b1 array([99, 2, 3, 4]) >>> a array([[99, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]])
使用copy
方法将创建数组及其数据的完整副本(深度复制)。要在您的数组上使用此方法,您可以运行:
>>> b2 = a.copy()
在此处了解更多关于副本和视图的信息。
基本数组操作
本节涵盖了加法、减法、乘法、除法等内容
创建数组后,您可以开始使用它们。例如,假设您已创建了两个数组,一个称为“data”,另一个称为“ones”。
您可以使用加号将数组相加。
>>> data = np.array([1, 2]) >>> ones = np.ones(2, dtype=int) >>> data + ones array([2, 3])
当然,您不仅可以进行加法运算!
>>> data - ones array([0, 1]) >>> data * data array([1, 4]) >>> data / data array([1., 1.])
NumPy 的基本操作非常简单。如果要找到数组中元素的总和,您可以使用sum()
。这适用于 1D 数组、2D 数组和更高维度的数组。
>>> a = np.array([1, 2, 3, 4]) >>> a.sum() 10
要在二维数组中添加行或列,您需要指定轴。
如果您从这个数组开始:
>>> b = np.array([[1, 1], [2, 2]])
您可以对行轴求和:
>>> b.sum(axis=0) array([3, 3])
您可以对列轴求和:
>>> b.sum(axis=1) array([2, 4])
在此处了解更多关于基本操作的信息。
广播
有时,您可能希望在数组和单个数字之间执行操作(也称为向量和标量之间的操作),或者在两个不同大小的数组之间执行操作。例如,您的数组(我们将其称为“data”)可能包含有关以英里为单位的距离的信息,但您希望将信息转换为公里。您可以执行此操作:
>>> data = np.array([1.0, 2.0]) >>> data * 1.6 array([1.6, 3.2])
NumPy 理解乘法应该在每个单元格中发生。这个概念称为广播。广播是一种机制,允许 NumPy 在不同形状的数组上执行操作。您的数组的维度必须兼容,例如,当两个数组的维度相等或其中一个为 1 时。如果维度不兼容,您将收到一个ValueError
。
在此处了解更多关于广播的信息。
更多有用的数组操作
本节涵盖了最大值、最小值、求和、平均值、乘积、标准差等内容
NumPy 还执行聚合函数。 除了min
,max
和sum
之外,你还可以轻松运行mean
来获得平均值,prod
来获得将元素相乘的结果,std
来获得标准偏差等。
>>> data.max() 2.0 >>> data.min() 1.0 >>> data.sum() 3.0
让我们从这个称为“a”的数组开始
>>> a = np.array([[0.45053314, 0.17296777, 0.34376245, 0.5510652], ... [0.54627315, 0.05093587, 0.40067661, 0.55645993], ... [0.12697628, 0.82485143, 0.26590556, 0.56917101]])
很常见的是想要沿着行或列进行聚合。 默认情况下,每个 NumPy 聚合函数都将返回整个数组的聚合值。 要找到数组中元素的和或最小值,请运行:
>>> a.sum() 4.8595784
或:
>>> a.min() 0.05093587
你可以指定要计算聚合函数的轴。 例如,你可以通过指定axis=0
来找到每列的最小值。
>>> a.min(axis=0) array([0.12697628, 0.05093587, 0.26590556, 0.5510652 ])
上述四个值对应于数组中的列数。 对于一个四列数组,你将获得四个值作为结果。
阅读更多关于数组方法的信息。
NumPy 1.26 中文官方指南(二)(4)https://developer.aliyun.com/article/1510609