NumPy相较于普通Python列表有哪些优势?
使用NumPy相比普通的Python列表有什么好处呢?
我有大约100个金融市场的数据系列,我打算创建一个100x100x100的立方体数组,也就是100万个单元格。我会对每个x、y和z进行回归分析,以填充数组中的标准误差。
我听说对于“大的矩阵”,我应该使用NumPy,而不是Python列表,这样在性能和扩展性上会更好。问题是,我已经会用Python列表了,它们对我来说似乎也能正常工作。
如果我换成NumPy,会有什么好处呢?
如果我有1000个系列(也就是立方体中有10亿个浮点单元格)呢?
7 个回答
Alex提到了内存效率,Roberto则提到了方便性,这两个观点都很不错。再补充几个想法,我想提到速度和功能性。
功能性:使用NumPy,你可以得到很多内置的功能,比如快速傅里叶变换(FFTs)、卷积、快速搜索、基本统计、线性代数、直方图等等。说真的,谁能没有快速傅里叶变换呢?
速度:这里有一个测试,比较了对一个列表和一个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,))
在我的系统上(当我在运行备份时)得到:
numpy: 3.004e-05
list: 5.363e-04
NumPy不仅效率高,而且使用起来也很方便。它提供了很多向量和矩阵的操作,这些操作可以让你省去很多不必要的工作。而且这些操作的实现也很高效。
举个例子,你可以直接从文件中读取一个立方体的数据到一个数组里:
x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))
沿着第二个维度求和:
s = x.sum(axis=1)
找出哪些单元格的值超过了某个阈值:
(x > 0.5).nonzero()
移除第三个维度上每个偶数索引的切片:
x[:, :, ::2]
另外,很多有用的库都是可以和NumPy数组一起使用的,比如统计分析和可视化的库。
即使你没有性能方面的问题,学习NumPy也是非常值得的。
NumPy的数组比Python的列表要紧凑得多。比如,你提到的“列表的列表”,在Python中可能至少需要20MB的内存,而一个包含单精度浮点数的NumPy三维数组只需要4MB。用NumPy读取和写入数据的速度也更快。
也许你对一百万个单元格不太在意,但如果是十亿个单元格,你肯定会在意。两种方法在32位系统上都无法处理,但在64位系统上,NumPy大约只需要4GB的内存,而单独使用Python则至少需要12GB(因为Python中有很多指针,指针的大小会翻倍),这就需要更贵的硬件了!
这种差别主要是因为“间接性”。Python的列表实际上是指向Python对象的指针数组,每个指针至少占用4个字节,再加上最小的Python对象需要16个字节(4个字节用于类型指针,4个字节用于引用计数,4个字节用于存储值,内存分配器会向上取整到16)。而NumPy数组则是一个统一值的数组——单精度数字每个占用4个字节,双精度的则占用8个字节。虽然灵活性较差,但你为标准Python列表的灵活性付出了不少代价!