NumPy是什么?

numpy是Python中科学计算的基本包。它是一个python库,提供多维数组对象、各种派生对象(如屏蔽数组和矩阵)以及各种用于对数组进行快速操作的例程,包括数学、逻辑、形状操作、排序、选择、I/O、离散傅立叶变换、基本线性代数、基本统计操作。随机模拟等等。

在 NumPy 的核心,是 ndarray 对象。它封装了 n -齐次数据类型的维度数组,许多操作是在编译后的代码中执行的,以提高性能。numpy数组和标准的python序列之间有几个重要的区别:

  • numpy数组在创建时的大小是固定的,与python列表不同(它可以动态增长)。更改的大小 ndarray 将创建新数组并删除原始数组。

  • numpy数组中的元素都需要具有相同的数据类型,因此内存中的元素大小相同。例外:可以有(python,包括numpy)对象数组,从而允许不同大小的元素数组。

  • numpy数组有助于对大量数据进行高级数学和其他类型的操作。通常,这样的操作比使用Python的内置序列更高效、代码更少。

  • 越来越多的基于python的科学和数学软件包正在使用numpy数组;尽管这些通常支持python序列输入,但它们在处理之前将这些输入转换为numpy数组,并且通常输出numpy数组。换言之,为了有效地使用当今基于python的科学/数学软件,仅仅知道如何使用python的内置序列类型是不够的——人们还需要知道如何使用numpy数组。

序列大小和速度在科学计算中尤为重要。作为一个简单的例子,考虑将一维序列中的每个元素与相同长度的另一个序列中的相应元素相乘的情况。如果数据存储在两个python列表中, ab ,我们可以迭代每个元素:

c = []
for i in range(len(a)):
    c.append(a[i]*b[i])

这会产生正确的答案,但如果 ab 每个包含数百万个数字,我们将为Python中的循环效率低下付出代价。通过编写代码,我们可以更快地在C语言中完成相同的任务(为了清晰起见,我们忽略变量声明和初始化、内存分配等)。

for (i = 0; i < rows; i++): {
  c[i] = a[i]*b[i];
}

这节省了解释python代码和操作python对象所涉及的所有开销,但代价是牺牲了用python编码所带来的好处。此外,所需的编码工作随着数据的维数而增加。例如,在二维数组的情况下,C代码(如前所述)扩展为

for (i = 0; i < rows; i++): {
  for (j = 0; j < columns; j++): {
    c[i][j] = a[i][j]*b[i][j];
  }
}

numpy为我们提供了两个方面的最佳选择:当 ndarray 包含,但元素对元素的操作由预编译的C代码快速执行。在NumPy

c = a * b

以接近C的速度执行前面的示例所做的操作,但是使用基于Python的代码简单性是我们所期望的。的确, NumPy 成语更简单!最后一个例子说明了numpy的两个特性,它们是其强大功能的基础:矢量化和广播。

为什么 NumPy 很快?

矢量化描述了代码中没有任何显式循环、索引等——当然,这些事情发生在优化的、预编译的C代码中,只是“幕后”。矢量化代码有很多优点,其中包括:

  • 矢量化代码更简洁,更易于阅读

  • 更少的代码行通常意味着更少的错误

  • 代码更像标准的数学符号(通常更容易对数学结构进行正确编码)

  • 矢量化导致更多的“ Python ”代码。如果没有矢量化,我们的代码将到处都是效率低下且难以读取的代码。 for 循环。

广播是一个术语,用来描述操作的每一个元素的行为;一般来说,在nummy中,所有的操作,不仅是算术操作,而且是逻辑的、位的、功能的等,都是以这种每一个元素的隐式方式表现的,即它们广播。此外,在上面的例子中, ab 可以是相同形状的多维数组,或者是一个标量和一个数组,或者甚至是两个形状不同的数组,前提是较小的数组可以“扩展”为较大的数组,这样生成的广播就不会模糊不清。广播的详细“规则”见 basics.broadcasting .

还有谁用 NumPy ?

Numpy完全支持面向对象的方法,再次使用 ndarray . 例如, ndarray 是一个类,拥有许多方法和属性。它的许多方法都被最外层 NumPy 的名称空间中的函数镜像,从而允许程序员使用他们喜欢的任何范式进行编码。这种灵活性允许numpy数组方言和numpy ndarray 类成为 de-facto Python中使用的多维数据交换语言。