NumPy优于常规Python列表有什么优势?

Tho*_*wne 439 python arrays numpy list numpy-ndarray

NumPy优于常规Python列表有什么优势?

我有大约100个金融市场系列,我打算创建一个100x100x100 = 100万个单元的立方体阵列.我将使用每个y和z对每个x进行回归(3变量),以使用标准错误填充数组.

我听说过,对于"大型矩阵",出于性能和可伸缩性的原因,我应该使用NumPy而不是Python列表.事实是,我知道Python列表,它们似乎对我有用.

如果我搬到NumPy,会有什么好处?

如果我有1000个系列(即立方体中有10亿个浮点单元)怎么办?

Ale*_*lli 699

NumPy的数组比Python列表更紧凑 - 如你所描述的,在Python中,列表的列表将至少需要20 MB左右,而单元格中具有单精度浮点数的NumPy 3D数组将适合4 MB.使用NumPy,读取和写入项目的访问速度也更快.

也许你对这一百万个单元并不那么关心,但是你绝对会选择十亿个单元 - 这两种方法都不适合32位架构,但是对于64位构建,NumPy会以4 GB左右的速度逃脱,Python本身至少需要大约12 GB(大量的指针,大小翻倍) - 一个更昂贵的硬件!

差异主要是由于"间接性" - Python列表是指向Python对象的指针数组,每个指针至少4个字节加上16个字节,即使是最小的Python对象(4个用于类型指针,4个用于引用计数,4个) for value - 内存分配器最多可达16个.NumPy数组是一个统一值的数组 - 单精度数字各占4个字节,双精度数字,8个字节.不太灵活,但您为标准Python列表的灵活性付出了大量代价!

  • 列表中的`getsizeof`只能告诉你列表对象本身消耗多少RAM以及数据数组中指针消耗的RAM,它不会告诉你这些指针引用的对象消耗了多少RAM. (4认同)
  • @JackSimpson`getsizeof`不可靠.文档清楚地指出:*只考虑直接归因于对象的内存消耗,而不是它所引用的对象的内存消耗.*这意味着如果你有嵌套的python列表,则不会考虑元素的大小帐户. (3认同)
  • 请注意,您对列表列表的等效 Python 列表大小的估计是错误的。C `float`s 的 4 GB numpy 数组(4 个字节)将转换为接近 32 GB 的 `list`s 和 Python `float`s(实际上是 C `double`s),而不是 12 GB;64 位 Python 上的每个 `float` 占用 ~24 字节(假设分配器中没有对齐丢失),加上 `list` 中的另外 8 个字节来保存引用(并且忽略了 `list` 的过度分配和对象头自己,这可能会添加另一个 GB,具体取决于发生了多少过度分配)。 (3认同)

Rob*_*let 226

NumPy不仅效率更高; 它也更方便.您可以免费获得大量的矢量和矩阵运算,这有时可以避免不必要的工作.它们也得到有效实施.

例如,您可以直接从文件中将多维数据集读取到数组中:

x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))
Run Code Online (Sandbox Code Playgroud)

沿第二个维度求和:

s = x.sum(axis=1)
Run Code Online (Sandbox Code Playgroud)

找出哪些单元格高于阈值:

(x > 0.5).nonzero()
Run Code Online (Sandbox Code Playgroud)

沿第三维删除每个偶数索引切片:

x[:, :, ::2]
Run Code Online (Sandbox Code Playgroud)

此外,许多有用的库与NumPy数组一起使用.例如,统计分析和可视化库.

即使您没有性能问题,学习NumPy也是值得的.

  • 谢谢 - 您在第三个示例中提供了另一个很好的理由,事实上,我将在矩阵中搜索高于阈值的单元格。此外,我是从 sqlLite 加载的。文件方法会更有效率。 (2认同)

tom*_*m10 107

亚历克斯提到了记忆效率,罗伯托提到了方便,这些都是好点.对于更多想法,我会提到速度功能.

功能:你可以通过NumPy,FFT,卷积,快速搜索,基本统计,线性代数,直方图等内置很多内容.真的,谁能在没有FFT的情况下生活?

速度:这是对列表和NumPy数组进行求和的测试,显示NumPy阵列上的总和快10倍(在此测试中 - 里程可能会有所不同).

from numpy import arange
from timeit import Timer

Nelements = 10000
Ntimeits = 10000

x = arange(Nelements)
y = range(Nelements)

t_numpy = Timer("x.sum()", "from __main__ import x")
t_list = Timer("sum(y)", "from __main__ import y")
print("numpy: %.3e" % (t_numpy.timeit(Ntimeits)/Ntimeits,))
print("list:  %.3e" % (t_list.timeit(Ntimeits)/Ntimeits,))
Run Code Online (Sandbox Code Playgroud)

在我的系统上(当我运行备份时)给出:

numpy: 3.004e-05
list:  5.363e-04
Run Code Online (Sandbox Code Playgroud)


Eli*_*zer 40

以下是scipy.org网站上常见问题解答的一个很好的答案:

NumPy阵列在(嵌套)Python列表中提供了哪些优势?

Python的列表是高效的通用容器.它们支持(相当)有效的插入,删除,追加和连接,Python的列表推导使它们易于构造和操作.但是,它们有一定的局限性:它们不支持元素化加法和乘法等"向量化"操作,并且它们可以包含不同类型的对象这一事实意味着Python必须存储每个元素的类型信息,并且必须执行类型调度代码在对每个元素进行操作时.这也意味着可以通过有效的C循环执行很少的列表操作 - 每次迭代都需要类型检查和其他Python API簿记.


小智 5

所有人都强调了numpy数组和python列表之间的几乎所有主要区别,在这里我将向大家简单介绍一下:

  1. Numpy数组在创建时具有固定的大小,这与python列表(可以动态增长)不同。更改ndarray的大小将创建一个新数组并删除原始数组。

  2. Numpy数组中的所有元素都必须具有相同的数据类型(我们也可以具有异构类型,但这将不允许您进行数学运算),因此在内存中的大小将相同

  3. Numpy数组有助于对大量数据进行数学运算和其他类型的运算。通常,与使用python顺序构建相比,此类操作执行效率更高且代码更少