关于数组:NumPy优于常规Python列表有什么优势?

What are the advantages of NumPy over regular Python lists?

与常规的python列表相比,numpy的优势是什么?

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

我听说对于"大型矩阵",出于性能和可伸缩性的考虑,我应该使用numpy而不是python列表。问题是,我知道python列表,它们似乎对我有用。

如果我搬去麻木会有什么好处?

如果我有1000个系列(也就是说,立方体中有10亿个浮点单元),会怎么样?


numpy的数组比python列表更紧凑——在python中,您描述的列表列表至少需要20 MB左右,而在单元格中具有单精度浮动的numpy 3D数组则可以容纳4 MB左右。使用numpy,读写项目的访问速度也更快。

也许你不太关心一百万个单元,但是你肯定会关心十亿个单元——这两种方法都不适合32位的体系结构,但是64位的构建,numpy可以摆脱4GB左右,仅python就至少需要12GB左右(大量指针的大小翻了一番)——一个更昂贵的硬件!

差异主要是由于"间接性"——python列表是指向python对象的指针数组,每个指针至少4个字节加上16个字节,即使是最小的python对象(4个用于类型指针,4个用于引用计数,4个用于值——内存分配器四舍五入为16)。numpy数组是一个统一值的数组——单精度数字每4个字节,双精度数字每8个字节。不太灵活,但是您为标准python列表的灵活性付出了巨大的代价!


numpy不仅效率更高,而且更方便。你可以免费得到很多向量和矩阵运算,这有时会让你避免不必要的工作。它们也得到了有效的实施。

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

1
x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))

沿第二维度求和:

1
s = x.sum(axis=1)

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

1
(x > 0.5).nonzero()

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

1
x[:, :, ::2]

此外,许多有用的库可以使用numpy数组。例如,统计分析和可视化库。

即使你没有表现问题,学习麻木也是值得努力的。


亚历克斯提到了记忆效率,罗伯托提到了便利性,这两者都是优点。关于更多的想法,我将提到速度和功能。

功能:通过numpy、ffts、卷积、快速搜索、基本统计、线性代数、柱状图等,您可以获得很多内置功能。实际上,谁可以不使用ffts生活?

速度:这里有一个关于对列表和numpy数组进行求和的测试,显示numpy数组的求和速度快10倍(在这个测试中,里程可能会有所不同)。

1
2
3
4
5
6
7
8
9
10
11
12
13
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,))

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

1
2
numpy: 3.004e-05
list:  5.363e-04

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

numpy数组比(嵌套的)python列表有哪些优势?

Python’s lists are efficient general-purpose containers. They support
(fairly) efficient insertion, deletion, appending, and concatenation,
and Python’s list comprehensions make them easy to construct and
manipulate. However, they have certain limitations: they don’t support
"vectorized" operations like elementwise addition and multiplication,
and the fact that they can contain objects of differing types mean
that Python must store type information for every element, and must
execute type dispatching code when operating on each element. This
also means that very few list operations can be carried out by
efficient C loops – each iteration would require type checks and other
Python API bookkeeping.


还请注意,TimeSeries SciKits中支持基于numpy的时间序列:

http://pytseries.sourceforge.net网站

对于回归,我非常肯定numpy将比列表更快更方便,甚至对于100^3问题。


所有这些都突出显示了numpy数组和python列表之间的几乎所有主要差异,我将在这里简要介绍它们:

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

  • numpy数组中的元素都需要具有相同的数据类型(我们也可以具有异构类型,但这不允许进行数学运算),因此在内存中的大小相同。

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