NumPy:初学者的绝对基础

欢迎来到NumPy的绝对初学者指南!如果您有任何意见或建议,请随时联系我们!

欢迎来到NumPy!

Numpy ( Numerical Python )是一个开源的Python库,几乎应用于科学和工程的每个领域。它是用Python处理数字数据的通用标准,是科学Python和PyData生态系统的核心。NumPy用户包括从最初的程序员到从事最先进的科学和工业研究与开发的有经验的研究人员。numpyapi广泛地用于Pandas、SciPy、Matplotlib、sciket learn、scikit image和大多数其他数据科学和科学Python包中。

NumPy库包含多维数组和矩阵数据结构(您将在后面的部分中找到有关这方面的更多信息)。它提供 恩达雷 ,一个均匀的n维数组对象,以及对其进行有效操作的方法。NumPy可以用于对数组执行各种各样的数学运算。它为Python添加了强大的数据结构,保证了数组和矩阵的高效计算,并提供了一个庞大的高级数学函数库,这些函数可以对这些数组和矩阵进行操作。

进一步了解 NumPy here 你说什么?

安装Numpy

要安装NumPy,我们强烈建议使用科学的Python发行版。如果您正在寻找在操作系统上安装NumPy的完整说明,您可以 find all of the details here .

如果您已经有Python,那么可以使用以下选项安装NumPy:

conda install numpy

或:

pip install numpy

如果您还没有Python,您可能需要考虑使用 Anaconda . 这是最简单的开始。获得这个发行版的好处是,您不需要过多担心单独安装NumPy或将用于数据分析的任何主要软件包,如pandas、sciket Learn等。

您可以在 Installation 截面位于 SciPy .

如何导入NumPy

任何时候你想在你的代码中使用一个包或库,你首先需要让它可以访问。

为了开始使用NumPy和NumPy中可用的所有函数,您需要导入它。这可以通过以下导入语句轻松完成:

import numpy as np

(我们缩短了 numpynp 为了节省时间并保持代码标准化,以便使用您的代码的任何人都可以轻松理解和运行它。)

阅读示例代码

如果您还不习惯阅读包含大量代码的教程,则可能不知道如何解释如下所示的代码块:

>>> a = np.arange(6)
>>> a2 = a[np.newaxis, :]
>>> a2.shape
(1, 6)

如果你不熟悉这种风格,很容易理解。如果你看到 >>> ,你在看 输入 ,或您要输入的代码。没有的一切 >>> 在它前面是 输出 ,或运行代码的结果。这是你跑步时看到的风格 python 在命令行上,但是如果使用IPython,可能会看到不同的样式。

Python列表和NumPy数组有什么区别?

NumPy提供了大量快速有效的方法来创建数组和处理数组中的数值数据。虽然Python列表可以在单个列表中包含不同的数据类型,但NumPy数组中的所有元素都应该是同质的。如果数组不是齐次的,那么要在数组上执行的数学运算将非常低效。

为什么要用NumPy?

NumPy数组比Python列表更快、更紧凑。阵列占用的内存较少,使用方便。NumPy使用更少的内存来存储数据,它提供了一种指定数据类型的机制。这使得代码可以进一步优化。

什么是数组?

数组是NumPy库的中心数据结构。数组是值的网格,它包含有关原始数据、如何定位元素以及如何解释元素的信息。它有一个元素网格,可以在 various ways . 这些元素都是同一类型的,称为数组 dtype .

数组可以由非负整数的元组、布尔、另一个数组或整数索引。这个 rank 数组的值是维数。这个 shape 数组的长度是一个整数元组,给出数组沿每个维度的大小。

初始化NumPy数组的一种方法是使用Python列表,对二维或更高维的数据使用嵌套列表。

例如::

>>> 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 array2D arrayndarrayvectormatrix


你可能偶尔会听到一个数组被称为“nArray”,它是“N维数组(N-dimensional array)”的缩写。你可能还会听到 1-D ,或一维数组, 2-D ,或二维数组,等等。Numpy ndarray 类用于表示矩阵和向量。一个 矢量(vector) 是一个一维数组(行向量和列向量之间没有区别),而 矩阵(matrix) 指二维数组。对于 3-D 或更高维数组,常使用 张量

数组的属性是什么?

数组通常是由相同类型和大小的项组成的固定大小的容器。数组中的维数和项数由其形状定义。数组的形状是一个非负整数元组,指定每个维度的大小。

在NumPy中,维度称为 axes . 这意味着如果您有一个如下所示的二维数组:

[[0., 0., 0.],
 [1., 1., 1.]]

你的数组有两个轴。第一轴的长度为2,第二轴的长度为3。

与其他Python容器对象一样,可以通过索引或切片数组来访问和修改数组的内容。不同于通常的数组,同一个数组中的不同对象可以共享不同的数据。

数组 属性 反映数组本身固有的信息。如果需要在不创建新数组的情况下获取甚至设置数组的属性,通常可以通过其属性访问数组。

Read more about array attributes here 并了解 array objects here .

如何创建基本数组

本节包括 np.array()np.zeros()np.ones()np.empty()np.arange()np.linspace()dtype


要创建NumPy数组,可以使用 np.array() .

创建一个简单数组所需要做的就是向它传递一个列表。如果选择,还可以指定列表中的数据类型。 You can find more information about data types here . ::

>>> import numpy as np
>>> a = np.array([1, 2, 3])

您可以通过以下方式可视化阵列:

../_images/np_array.png

对这些概念的理解和理解意味着简单化。数组和数组操作比这里捕获的要复杂得多!

除了从元素序列创建数组外,还可以轻松地创建一个填充 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])

Learn more about creating arrays here

添加、删除和排序元素

本节包括 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()


Yes!

使用 arr.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 ,可以指定几个可选参数:

>>> numpy.reshape(a, newshape=(1, 6), order='C')
array([[0, 1, 2, 3, 4, 5]])

a 是要重塑的数组。

newshape 是你想要的新形状。可以指定整数或整数元组。如果指定整数,则结果将是该长度的数组。形状应与原始形状兼容。

order: C 表示使用类C索引顺序读/写元素, F 表示使用类似Fortran的索引顺序读/写元素, A 如果一个Fortran在内存中是连续的,则表示以类似Fortran的索引顺序读/写元素;否则,表示以类似C的顺序读/写元素。(这是一个可选参数,不需要指定。)

如果您想了解C和Fortran order的更多信息,可以 read more about the internal organization of NumPy arrays here . 基本上,C和Fortran顺序与索引如何对应数组在内存中的存储顺序有关。在Fortran语言中,当二维数组存储在内存中时,在遍历数组元素时 第一 指数是变化最快的指数。随着第一个索引移动到下一行,矩阵一次存储一列。这就是为什么Fortran被认为是 Column-major language . 另一方面,在C中 last 指数变化最快。矩阵按行存储,使其成为 Row-major language . 您对C或Fortran所做的工作取决于保留索引约定与否对数据重新排序更为重要。

Learn more about shape manipulation here .

如何将一维数组转换为二维数组(如何向数组添加新轴)

本节包括 np.newaxisnp.expand_dims


你可以使用 np.newaxisnp.expand_dims 增加现有数组的维数。

使用 np.newaxis 使用一次将使数组的维数增加一个维数。这意味着 1D 数组将成为 2D 阵列,a 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 . 例如,可以通过沿第一个维度插入轴将一维数组转换为行向量:

>>> 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 hereexpand_dimsexpand_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])

你可以这样想象:

../_images/np_indexing.png

您可能需要获取数组的一部分或特定数组元素,以便在进一步分析或其他操作中使用。为此,需要对数组进行子集、切片和/或索引。

如果您想从数组中选择满足特定条件的值,那么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))

进一步了解 indexing and slicing herehere .

有关在以下位置使用非零函数的详细信息: nonzero .

如何从现有数据创建数组

本节包括 slicing and indexingnp.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]])]

Learn more about stacking and splitting arrays here .

你可以使用 view 方法创建一个新的数组对象,该对象查看与原始数组相同的数据(a 浅拷贝

观点是一个重要的概念!NumPy函数以及索引和切片等操作将尽可能返回视图。这节省了内存,而且速度更快(不需要复制数据)。不过,要注意这一点很重要—在视图中修改数据也会修改原始数组!

假设您创建了以下数组:

>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])

现在我们创建一个数组 b1 通过切片 a 并修改 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 方法将生成数组及其数据的完整副本(a 深拷贝 ). 要在阵列上使用此选项,可以运行:

>>> b2 = a.copy()

Learn more about copies and views here .

基本阵列操作

本节介绍加法、减法、乘法、除法等


一旦创建了数组,就可以开始使用它们了。例如,假设您创建了两个数组,一个称为“data”,另一个称为“one”

../_images/np_array_dataones.png

可以将数组与加号一起添加。

>>> data = np.array([1, 2])
>>> ones = np.ones(2, dtype=int)
>>> data + ones
array([2, 3])
../_images/np_data_plus_ones.png

当然,你可以做的不仅仅是加法!

>>> data - ones
array([0, 1])
>>> data * data
array([1, 4])
>>> data / data
array([1., 1.])
../_images/np_sub_mult_divide.png

NumPy的基本操作很简单。如果要求数组中元素的和,可以使用 sum() . 这适用于一维阵列、二维阵列和高维阵列。:

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

Learn more about basic operations here .

广播

有时您可能需要在数组和单个数字(也称为 向量和标量之间的运算 )或者在两个不同大小的数组之间。例如,您的数组(我们称之为“数据”)可能包含以英里为单位的距离信息,但您希望将这些信息转换为公里。您可以通过以下方式执行此操作:

>>> data = np.array([1.0, 2.0])
>>> data * 1.6
array([1.6, 3.2])
../_images/np_multiply_broadcasting.png

NumPy明白乘法应该发生在每个细胞上。这个概念叫做 广播 . 广播是一种允许NumPy对不同形状的数组执行操作的机制。数组的维数必须兼容,例如,当两个数组的维数相等或其中一个为1时。如果尺寸不兼容,您将得到 ValueError .

Learn more about broadcasting here .

更有用的数组操作

本节包括最大值、最小值、总和、平均值、乘积、标准差等


NumPy还执行聚合功能。除了 minmaxsum ,您可以轻松地运行 mean 为了得到平均值, prod 为了得到元素相乘的结果, std 得到标准差,等等。:

>>> data.max()
2.0
>>> data.min()
1.0
>>> data.sum()
3.0
../_images/np_aggregation.png

让我们从这个名为“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 ])

上面列出的四个值对应于数组中的列数。使用四列数组,您将得到四个值作为结果。

阅读更多有关 array methods here .

创建矩阵

您可以传递Python列表来创建一个二维数组(或“矩阵”),用NumPy表示它们。:

>>> data = np.array([[1, 2], [3, 4]])
>>> data
array([[1, 2],
       [3, 4]])
../_images/np_create_matrix.png

在处理矩阵时,索引和切片操作非常有用:

>>> data[0, 1]
2
>>> data[1:3]
array([[3, 4]])
>>> data[0:2, 0]
array([1, 3])
../_images/np_matrix_indexing.png

可以用聚合向量的方法聚合矩阵:

>>> data.max()
4
>>> data.min()
1
>>> data.sum()
10
../_images/np_matrix_aggregation.png

可以聚合矩阵中的所有值,也可以使用 axis 参数::

>>> data.max(axis=0)
array([3, 4])
>>> data.max(axis=1)
array([2, 4])
../_images/np_matrix_aggregation_row.png

一旦创建了矩阵,如果有两个大小相同的矩阵,就可以使用算术运算符将它们相加和相乘。:

>>> data = np.array([[1, 2], [3, 4]])
>>> ones = np.array([[1, 1], [1, 1]])
>>> data + ones
array([[2, 3],
       [4, 5]])
../_images/np_matrix_arithmetic.png

可以对不同大小的矩阵执行这些算术运算,但前提是一个矩阵只有一列或一行。在这种情况下,NumPy将使用其广播规则进行操作。:

>>> data = np.array([[1, 2], [3, 4], [5, 6]])
>>> ones_row = np.array([[1, 1]])
>>> data + ones_row
array([[2, 3],
       [4, 5],
       [6, 7]])
../_images/np_matrix_broadcasting.png

请注意,当NumPy打印N维数组时,最后一个轴的循环速度最快,而第一个轴的循环速度最慢。例如::

>>> np.ones((4, 3, 2))
array([[[1., 1.],
        [1., 1.],
        [1., 1.]],

       [[1., 1.],
        [1., 1.],
        [1., 1.]],

       [[1., 1.],
        [1., 1.],
        [1., 1.]],

       [[1., 1.],
        [1., 1.],
        [1., 1.]]])

我们经常希望NumPy初始化数组的值。NumPy提供如下功能 ones()zeros()random.Generator 类生成随机数。您所需要做的就是传入要生成的元素数:

>>> np.ones(3)
array([1., 1., 1.])
>>> np.zeros(3)
array([0., 0., 0.])
# the simplest way to generate random numbers
>>> rng = np.random.default_rng(0)
>>> rng.random(3)
array([0.63696169, 0.26978671, 0.04097352])
../_images/np_ones_zeros_random.png

您也可以使用 ones()zeros()random() 若要创建二维数组,请为它们提供描述矩阵维度的元组:

>>> np.ones((3, 2))
array([[1., 1.],
       [1., 1.],
       [1., 1.]])
>>> np.zeros((3, 2))
array([[0., 0.],
       [0., 0.],
       [0., 0.]])
>>> rng.random((3, 2))
array([[0.01652764, 0.81327024],
       [0.91275558, 0.60663578],
       [0.72949656, 0.54362499]])  # may vary
../_images/np_ones_zeros_matrix.png

阅读有关创建数组的更多信息 0 的, 1 的,其他值或未初始化,位于 array creation routines .

生成随机数

使用随机数生成是许多数值和机器学习算法配置和评估的重要部分。无论您需要在人工神经网络中随机初始化权重、将数据拆分为随机集,还是随机洗牌数据集,都必须能够生成随机数(实际上是可重复的伪随机数)。

Generator.integers ,您可以生成从低(记住这是包含NumPy)到高(排除)的随机整数。你可以设置 endpoint=True 使高数字包含在内。

您可以使用以下命令生成0到4之间的2 x 4随机整数数组:

>>> rng.integers(5, size=(2, 4))
array([[2, 1, 1, 0],
       [0, 0, 0, 4]])  # may vary

Read more about random number generation here .

如何获得独特的项目和计数

本节包括 np.unique()


您可以使用 np.unique .

例如,如果从以下数组开始:

>>> a = np.array([11, 11, 12, 13, 14, 15, 16, 17, 12, 13, 11, 14, 18, 19, 20])

你可以用 np.unique 要打印数组中的唯一值:

>>> unique_values = np.unique(a)
>>> print(unique_values)
[11 12 13 14 15 16 17 18 19 20]

要获得NumPy数组(数组中唯一值的第一个索引位置的数组)中唯一值的索引,只需传递 return_index 论点 np.unique() 以及你的阵型。:

>>> unique_values, indices_list = np.unique(a, return_index=True)
>>> print(indices_list)
[ 0  2  3  4  5  6  7 12 13 14]

你可以通过 return_counts 论点 np.unique() 与数组一起获取NumPy数组中唯一值的频率计数。:

>>> unique_values, occurrence_count = np.unique(a, return_counts=True)
>>> print(occurrence_count)
[3 2 2 2 1 1 1 1 1 1]

这也适用于二维数组!如果从这个数组开始:

>>> a_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]])

您可以通过以下方式找到唯一的值:

>>> unique_values = np.unique(a_2d)
>>> print(unique_values)
[ 1  2  3  4  5  6  7  8  9 10 11 12]

如果未传递axis参数,则二维数组将被展平。

如果要获取唯一的行或列,请确保传递 axis 争论。要查找唯一行,请指定 axis=0 对于列,指定 axis=1 . ::

>>> unique_rows = np.unique(a_2d, axis=0)
>>> print(unique_rows)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

要获取唯一行、索引位置和出现次数,可以使用:

>>> unique_rows, indices, occurrence_count = np.unique(
...      a_2d, axis=0, return_counts=True, return_index=True)
>>> print(unique_rows)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
>>> print(indices)
[0 1 2]
>>> print(occurrence_count)
[2 1 1]

要了解有关在数组中查找唯一元素的详细信息,请参见 unique .

变换和重塑矩阵

本节包括 arr.reshape()arr.transpose()arr.T


通常需要变换矩阵。NumPy数组具有 T 它允许你变换矩阵。

../_images/np_transposing_reshaping.png

您可能还需要切换矩阵的维度。例如,当您有一个模型需要与数据集不同的特定输入形状时,就会发生这种情况。这就是 reshape 方法可能有用。您只需传入矩阵所需的新维度。:

>>> data.reshape(2, 3)
array([[1, 2, 3],
       [4, 5, 6]])
>>> data.reshape(3, 2)
array([[1, 2],
       [3, 4],
       [5, 6]])
../_images/np_reshape.png

您也可以使用 .transpose() 根据指定的值反转或更改阵列的轴。

如果从这个数组开始:

>>> arr = np.arange(6).reshape((2, 3))
>>> arr
array([[0, 1, 2],
       [3, 4, 5]])

你可以用 arr.transpose() . ::

>>> arr.transpose()
array([[0, 3],
       [1, 4],
       [2, 5]])

您也可以使用 arr.T ::

>>> arr.T
array([[0, 3],
       [1, 4],
       [2, 5]])

要了解有关转置和重塑数组的详细信息,请参见 transposereshape .

如何反转数组

本节包括 np.flip()


NumPy 的 np.flip() 函数允许您沿轴翻转或反转数组的内容。使用时 np.flip() ,指定要反转的数组和轴。如果不指定轴,NumPy将沿输入数组的所有轴反转内容。

反转1D阵列

如果你从一个像这样的一维数组开始:

>>> arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])

你可以倒过来说:

>>> reversed_arr = np.flip(arr)

如果要打印反转数组,可以运行:

>>> print('Reversed Array: ', reversed_arr)
Reversed Array:  [8 7 6 5 4 3 2 1]

反转二维阵列

二维阵列的工作原理大致相同。

如果从这个数组开始:

>>> arr_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])

可以使用以下命令反转所有行和列中的内容:

>>> reversed_arr = np.flip(arr_2d)
>>> print(reversed_arr)
[[12 11 10  9]
 [ 8  7  6  5]
 [ 4  3  2  1]]

你可以很容易地逆转 rows 用:

>>> reversed_arr_rows = np.flip(arr_2d, axis=0)
>>> print(reversed_arr_rows)
[[ 9 10 11 12]
 [ 5  6  7  8]
 [ 1  2  3  4]]

或者只反转 用:

>>> reversed_arr_columns = np.flip(arr_2d, axis=1)
>>> print(reversed_arr_columns)
[[ 4  3  2  1]
 [ 8  7  6  5]
 [12 11 10  9]]

也可以只反转一列或一行的内容。例如,可以反转索引位置1(第二行)处的行内容:

>>> arr_2d[1] = np.flip(arr_2d[1])
>>> print(arr_2d)
[[ 1  2  3  4]
 [ 8  7  6  5]
 [ 9 10 11 12]]

也可以反转索引位置1处的列(第二列)::

>>> arr_2d[:,1] = np.flip(arr_2d[:,1])
>>> print(arr_2d)
[[ 1 10  3  4]
 [ 8  7  6  5]
 [ 9  2 11 12]]

了解有关反转阵列的更多信息,请访问 flip .

重塑和展平多维数组

本节包括 .flatten()ravel()


有两种常用的展平阵列的方法: .flatten().ravel() . 两者之间的主要区别在于,使用 ravel() 实际上是对父数组的引用(即“视图”)。这意味着对新数组的任何更改也将影响父数组。自 ravel 不创建副本,它的内存效率。

如果从这个数组开始:

>>> x = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])

你可以使用 flatten 将你的阵型展平为1D阵型。:

>>> x.flatten()
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

当你使用 flatten ,对新数组的更改不会更改父数组。

例如::

>>> a1 = x.flatten()
>>> a1[0] = 99
>>> print(x)  # Original array
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
>>> print(a1)  # New array
[99  2  3  4  5  6  7  8  9 10 11 12]

但是当你使用 ravel ,对新数组所做的更改将影响父数组。

例如::

>>> a2 = x.ravel()
>>> a2[0] = 98
>>> print(x)  # Original array
[[98  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
>>> print(a2)  # New array
[98  2  3  4  5  6  7  8  9 10 11 12]

阅读更多有关 flattenndarray.flattenravelravel .

如何访问docstring以获取更多信息

本节包括 help()???


当谈到数据科学生态系统时,Python和NumPy都是以用户为中心构建的。最好的例子之一就是内置的文档访问。每个对象都包含对字符串的引用,该字符串称为 文档字符串 . 在大多数情况下,此docstring包含对象及其使用方法的快速简明摘要。Python有一个内置的 help() 可以帮助您访问此信息的函数。这意味着,几乎任何时候你需要更多的信息,你可以使用 help() 快速找到您需要的信息。

例如::

>>> help(max)
Help on built-in function max in module builtins:

max(...)
    max(iterable, *[, default=obj, key=func]) -> value
    max(arg1, arg2, *args, *[, key=func]) -> value

    With a single iterable argument, return its biggest item. The
    default keyword-only argument specifies an object to return if
    the provided iterable is empty.
    With two or more arguments, return the largest argument.

因为访问附加信息非常有用,所以IPython使用 ? 字符作为访问此文档以及其他相关信息的速记。IPython是一个用于多种语言交互计算的命令shell。 You can find more information about IPython here .

例如:

In [0]: max?
max(iterable, *[, default=obj, key=func]) -> value
max(arg1, arg2, *args, *[, key=func]) -> value

With a single iterable argument, return its biggest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the largest argument.
Type:      builtin_function_or_method

您甚至可以将此符号用于对象方法和对象本身。

假设您创建了以下数组:

>>> a = np.array([1, 2, 3, 4, 5, 6])

然后您可以获得许多有用的信息(关于 a 本身,后跟 ndarray 其中 a 是实例):

In [1]: a?
Type:            ndarray
String form:     [1 2 3 4 5 6]
Length:          6
File:            ~/anaconda3/lib/python3.7/site-packages/numpy/__init__.py
Docstring:       <no docstring>
Class docstring:
ndarray(shape, dtype=float, buffer=None, offset=0,
        strides=None, order=None)

An array object represents a multidimensional, homogeneous array
of fixed-size items.  An associated data-type object describes the
format of each element in the array (its byte-order, how many bytes it
occupies in memory, whether it is an integer, a floating point number,
or something else, etc.)

Arrays should be constructed using `array`, `zeros` or `empty` (refer
to the See Also section below).  The parameters given here refer to
a low-level method (`ndarray(...)`) for instantiating an array.

For more information, refer to the `numpy` module and examine the
methods and attributes of an array.

Parameters
----------
(for the __new__ method; see Notes below)

shape : tuple of ints
        Shape of created array.
...

这也适用于函数和其他 you 创建。只需记住在函数中包含一个docstring,该函数使用字符串文字 (""" """''' ''' 围绕您的文档)。

例如,如果创建以下函数:

>>> def double(a):
...   '''Return a * 2'''
...   return a * 2

您可以获取有关函数的信息:

In [2]: double?
Signature: double(a)
Docstring: Return a * 2
File:      ~/Desktop/<ipython-input-23-b5adf20be596>
Type:      function

通过阅读感兴趣对象的源代码,您可以获得另一级别的信息。使用双问号 (?? )允许您访问源代码。

例如:

In [3]: double??
Signature: double(a)
Source:
def double(a):
    '''Return a * 2'''
    return a * 2
File:      ~/Desktop/<ipython-input-23-b5adf20be596>
Type:      function

如果所讨论的对象是用Python以外的语言编译的,则使用 ?? 将返回与 ? . 您将在许多内置对象和类型中发现这一点,例如:

In [4]: len?
Signature: len(obj, /)
Docstring: Return the number of items in a container.
Type:      builtin_function_or_method

以及:

In [5]: len??
Signature: len(obj, /)
Docstring: Return the number of items in a container.
Type:      builtin_function_or_method

具有相同的输出,因为它们是用Python以外的编程语言编译的。

使用数学公式

易于实现在数组上工作的数学公式是使NumPy在科学Python社区中得到如此广泛应用的原因之一。

例如,这是均方误差公式(处理回归的有监督机器学习模型中使用的中心公式):

../_images/np_MSE_formula.png

在NumPy中实现此公式简单明了:

../_images/np_MSE_implementation.png

使这项工作如此成功的原因是 predictionslabels 可以包含一个或一千个值。它们只需要大小相同。

你可以这样想象:

../_images/np_mse_viz1.png

在本例中,预测和标签向量都包含三个值,即 n 值为3。在我们执行减法之后,向量中的值是平方的。然后NumPy对这些值求和,结果就是该预测的错误值和模型质量的分数。

../_images/np_mse_viz2.png ../_images/np_MSE_explanation2.png

如何保存和加载NumPy对象

本节包括 np.savenp.saveznp.savetxtnp.loadnp.loadtxt


在某个时候,您可能希望将阵列保存到磁盘并将其加载回,而无需重新运行代码。幸运的是,使用NumPy保存对象有几种方法。ndarray对象可以通过 loadtxtsavetxt 处理普通文本文件的函数, loadsave 使用 .npy 文件扩展名和 savez 函数,该函数使用 .npz 文件扩展名。

这个 .npy.npz 文件存储数据、形状、数据类型和重建数据阵列所需的其他信息,即使文件位于具有不同体系结构的另一台计算机上,也能正确检索阵列。

如果要存储单个ndarray对象,请使用将其存储为.npy文件 np.save . 如果要在单个文件中存储多个ndarray对象,请使用将其另存为.npz文件 np.savez . 您还可以将多个数组以压缩的npz格式保存到一个文件中 savez_compressed .

它很容易保存、加载和数组 np.save() . 并确保只需要指定一个数组名。例如,如果创建以下数组:

>>> a = np.array([1, 2, 3, 4, 5, 6])

您可以将其另存为“文件名.npy“与::

>>> np.save('filename', a)

你可以使用 np.load() 重建阵列。:

>>> b = np.load('filename.npy')

如果要检查数组,可以运行:::

>>> print(b)
[1 2 3 4 5 6]

可以将NumPy数组保存为纯文本文件,如 .csv.txt 用文件 np.savetxt .

例如,如果创建以下数组:

>>> csv_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])

您可以轻松地将其保存为名为“new”的.csv文件_文件.csv“像这样:

>>> np.savetxt('new_file.csv', csv_arr)

您可以使用快速方便地加载保存的文本文件 loadtxt() ::

>>> np.loadtxt('new_file.csv')
array([1., 2., 3., 4., 5., 6., 7., 8.])

这个 savetxt()loadtxt() 函数接受其他可选参数,如页眉、页脚和分隔符。虽然文本文件更易于共享,.npy和.npz文件更小,读取速度更快。如果需要对文本文件进行更复杂的处理(例如,如果需要处理包含缺少值的行),则需要使用 genfromtxt 功能。

savetxt ,可以指定页眉、页脚、注释等。

进一步了解 input and output routines here .

导入和导出CSV

在包含现有信息的CSV中读取很简单。最好最简单的方法就是使用 Pandas . ::

>>> import pandas as pd

>>> # If all of your columns are the same type:
>>> x = pd.read_csv('music.csv', header=0).values
>>> print(x)
[['Billie Holiday' 'Jazz' 1300000 27000000]
 ['Jimmie Hendrix' 'Rock' 2700000 70000000]
 ['Miles Davis' 'Jazz' 1500000 48000000]
 ['SIA' 'Pop' 2000000 74000000]]

>>> # You can also simply select the columns you need:
>>> x = pd.read_csv('music.csv', usecols=['Artist', 'Plays']).values
>>> print(x)
[['Billie Holiday' 27000000]
 ['Jimmie Hendrix' 70000000]
 ['Miles Davis' 48000000]
 ['SIA' 74000000]]
../_images/np_pandas.png

使用Pandas导出数组也很简单。如果您是NumPy新手,您可能需要从数组中的值创建一个Pandas数据帧,然后使用Pandas将数据帧写入CSV文件。

如果创建了此数组“a”:

>>> a = np.array([[-2.58289208,  0.43014843, -1.24082018, 1.59572603],
...               [ 0.99027828, 1.17150989,  0.94125714, -0.14692469],
...               [ 0.76989341,  0.81299683, -0.95068423, 0.11769564],
...               [ 0.20484034,  0.34784527,  1.96979195, 0.51992837]])

您可以创建一个数据帧:

>>> df = pd.DataFrame(a)
>>> print(df)
          0         1         2         3
0 -2.582892  0.430148 -1.240820  1.595726
1  0.990278  1.171510  0.941257 -0.146925
2  0.769893  0.812997 -0.950684  0.117696
3  0.204840  0.347845  1.969792  0.519928

您可以使用以下工具轻松保存数据帧:

>>> df.to_csv('pd.csv')

并阅读您的CSV:

>>> data = pd.read_csv('pd.csv')
../_images/np_readcsv.png

你也可以用NumPy保存你的数组 savetxt 方法。::

>>> np.savetxt('np.csv', a, fmt='%.2f', delimiter=',', header='1,  2,  3,  4')

如果使用的是命令行,则可以随时使用以下命令读取保存的CSV:

$ cat np.csv
#  1,  2,  3,  4
-2.58,0.43,-1.24,1.60
0.99,1.17,0.94,-0.15
0.77,0.81,-0.95,0.12
0.20,0.35,1.97,0.52

或者你可以随时用文本编辑器打开文件!

如果你有兴趣了解更多关于熊猫的知识,可以看看 official Pandas documentation . 了解如何使用 official Pandas installation information .

使用Matplotlib打印阵列

如果你需要为你的值生成一个曲线图,它非常简单 Matplotlib .

例如,您可能有这样一个数组:

>>> a = np.array([2, 1, 5, 7, 4, 6, 8, 14, 10, 9, 18, 20, 22])

如果已安装Matplotlib,则可以使用以下选项导入:

>>> import matplotlib.pyplot as plt

# If you're using Jupyter Notebook, you may also want to run the following
# line of code to display your code in the notebook:

%matplotlib inline

要绘制值,只需运行:

>>> plt.plot(a)

# If you are running from a command line, you may need to do this:
# >>> plt.show()
../_images/matplotlib1.png

例如,可以这样绘制一维数组:

>>> x = np.linspace(0, 5, 20)
>>> y = np.linspace(0, 10, 20)
>>> plt.plot(x, y, 'purple') # line
>>> plt.plot(x, y, 'o')      # dots
../_images/matplotlib2.png

使用Matplotlib,您可以访问大量的可视化选项。:

>>> from mpl_toolkits.mplot3d import Axes3D
>>> fig = plt.figure()
>>> ax = Axes3D(fig)
>>> X = np.arange(-5, 5, 0.15)
>>> Y = np.arange(-5, 5, 0.15)
>>> X, Y = np.meshgrid(X, Y)
>>> R = np.sqrt(X**2 + Y**2)
>>> Z = np.sin(R)

>>> ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='viridis')
../_images/matplotlib3.png

要阅读更多关于Matplotlib及其功能的信息,请看 the official documentation . 有关安装Matplotlib的说明,请参阅官方 installation section .


Image credits: Jay Alammar http://jalammar.github.io/