什么是 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 数组。
关于序列大小和速度的观点在科学计算中尤为重要。举一个简单的例子,考虑将 1-D 序列中的每个元素与另一个相同长度的序列中的相应元素相乘的情况。如果数据存储在两个 Python 列表a
和b
中,我们可以遍历每个元素:
c = []
for i in range(len(a)):
c.append(a[i]*b[i])
这可以得出正确的答案,但如果a
和b
中各包含数百万个数字,那么我们将为在 Python 中循环的低效率付出代价。 我们可以在 C 中写得更快完成相同的任务(出于清晰起见,我们忽略变量声明、初始化、内存分配等)
for (i = 0; i < rows; i++) {
c[i] = a[i]*b[i];
}
这节省了解释 Python 代码并操纵 Python 对象所涉及的所有开销,但代价是放弃了使用 Python 编程获得的好处。此外,随着数据维度的增加,所需的编码工作也会增加。例如,在 2-D 数组的情况下,之前缩写为 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 代码“在幕后”方式进行。矢量化代码有许多优势,其中包括:
-
矢量化代码更简洁,更易读
-
更少的代码行通常意味着更少的错误
-
代码更接近标准数学符号表示法(通常使数学构造的正确编码更容易)
-
矢量化导致了更“Pythonic”的代码。没有矢量化,我们的代码将充斥着效率低下且难以阅读的
for
循环。
广播是用来描述操作的隐式逐点行为的术语;一般来说,在 NumPy 中,所有操作(不仅仅是算术操作,还有逻辑、位运算、函数等)都以这种隐式逐点方式行为,即它们进行广播。此外,在上面的示例中,a
和 b
可能是相同形状的多维数组,或者是标量和数组,甚至是两个形状不同的数组,只要较小的数组可以“扩展”到大数组的形状,使得结果的广播是明确的。有关广播的详细“规则”请参见 Broadcasting。
谁还在使用 NumPy?
NumPy 充分支持面向对象的方法,再次从 ndarray 开始。例如,ndarray 是一个类,拥有 numerous 方法和属性。它的许多方法与 NumPy 最外层命名空间中的函数相对应,允许程序员使用他们偏好的任何范例编码。这种灵活性使得 NumPy 数组方言和 NumPy ndarray 类成为 Python 中用于多维数据交换的事实上语言。
为什么 NumPy 如此快速?
矢量化描述代码中的任何显式循环、索引等都不存在——当然,这些事情当然存在,只是以优化的、预编译的 C 代码“在幕后”方式进行。矢量化代码有许多优势,其中包括:
-
向量化的代码更简洁,更易读。
-
更少的代码行通常意味着更少的错误。
-
代码更接近标准数学表示法(通常更容易正确编写数学结构)。
-
向量化导致更“Pythonic”的代码。没有向量化,我们的代码将充满效率低下且难以阅读的
for
循环。
广播是用来描述操作的隐式逐元素行为的术语;一般来说,在 NumPy 中所有操作,不仅仅是算术操作,还包括逻辑、位操作、函数等等,都以这种隐式逐元素的方式进行,即它们进行广播。此外,在上面的示例中,a
和 b
可以是相同形状的多维数组,或者是标量和数组,甚至是两个形状不同的数组,只要较小的数组可以“扩展”到较大数组的形状,使得结果的广播不会产生歧义即可。有关广播的详细“规则”,请参阅广播。
谁还在使用 NumPy?
NumPy 完全支持面向对象的方法,再次以 ndarray 为例。例如,ndarray 是一个类,拥有许多方法和属性。其中许多方法在 NumPy 最外层的命名空间中都有相应的函数,使程序员可以按照他们喜欢的范式编码。这种灵活性使得 NumPy 数组方言和 NumPy ndarray 类成为 Python 中多维数据交换的事实标准语言。