NumPy 1.26 中文官方指南(二)(3)

简介: NumPy 1.26 中文官方指南(二)

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.ndimndarray.sizendarray.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.newaxisnp.expand_dims


你可以使用 np.newaxisnp.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 获取了你数组的一个部分。

你也可以垂直和水平地堆叠两个现有数组。假设你有两个数组,a1a2

>>> 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 还执行聚合函数。 除了minmaxsum之外,你还可以轻松运行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

相关文章
|
6月前
|
Python
NumPy 1.26 中文官方指南(五)
NumPy 1.26 中文官方指南(五)
48 1
|
6月前
|
BI 索引 Python
NumPy 1.26 中文官方指南(一)(2)
NumPy 1.26 中文官方指南(一)
80 1
NumPy 1.26 中文官方指南(一)(2)
|
6月前
|
索引 Python
NumPy 1.26 中文官方指南(一)(4)
NumPy 1.26 中文官方指南(一)
61 1
|
6月前
|
存储 BI 索引
NumPy 1.26 中文官方指南(一)(3)
NumPy 1.26 中文官方指南(一)
44 1
|
6月前
|
存储 程序员 BI
NumPy 1.26 中文官方指南(一)(1)
NumPy 1.26 中文官方指南(一)
65 1
|
6月前
|
存储 程序员 API
NumPy 1.26 中文官方指南(四)(1)
NumPy 1.26 中文官方指南(四)
47 1
|
6月前
|
并行计算 PyTorch 算法框架/工具
NumPy 1.26 中文官方指南(三)(4)
NumPy 1.26 中文官方指南(三)
87 1
|
6月前
|
编译器 C语言 C++
NumPy 1.26 中文官方指南(三)(2)
NumPy 1.26 中文官方指南(三)
90 1
|
6月前
|
存储 数据建模 索引
NumPy 1.26 中文官方指南(三)(1)
NumPy 1.26 中文官方指南(三)
80 1
|
6月前
|
机器学习/深度学习 存储 数据可视化
NumPy 1.26 中文官方指南(二)(4)
NumPy 1.26 中文官方指南(二)
81 1