上一个主题

设置

下一个主题

安装NumPy

什么是NumPy?

NumPy是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的两个特点,它们是其大部分功能的基础:矢量化和广播。

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

  • 矢量化代码更简洁易读
  • 较少的代码行通常意味着更少的错误
  • 该代码更接近于标准的数学符号(使代码正确地编写数学结构更容易)
  • 矢量化会导致更多的“Pythonic”代码。如果没有向量化,我们的代码会被浪费在效率低下,难以读取for循环中。

广播是用来描述操作隐含的逐个元素行为的术语;一般而言,在NumPy中,所有的操作,不仅算术操作,而且逻辑的,按位的,功能的等等,都以这种隐含的逐元素方式表现,即它们广播。此外,在上面的示例中,ab可以是相同形状的多维数组,或者是标量和数组,或者甚至是具有不同形状的两个数组,较小的阵列是“可扩展的”到更大的形状,使得得到的广播是明确的。有关广播的详细“规则”,请参阅numpy.doc.broadcasting

NumPy完全支持面向对象的方法,再次用ndarray开始。For example, ndarray is a class, possessing numerous methods and attributes. 它的许多方法在最外面的NumPy命名空间中映射函数,使程序员可以完全自由地编写代码,无论她喜欢哪种模式和/或哪种模式看起来最适合当前的任务。