参考Why NumPy instead of Python lists?
tom10说:速度:这是对列表和NumPy数组进行求和的测试,显示NumPy数组上的总和快10倍(在此测试中 - 里程可能会有所不同)。
但我的测试使用以下代码:
import numpy as np
import time as time
N = 100000
#using numpy
start = time.time()
array = np.array([])
for i in range(N):
array = np.append(array, i)
end = time.time()
print ("Using numpy: ", round(end-start, 2), end="\n")
#using list
start = time.time()
list = []
for i in range(N):
list.append(i)
list = np.array(list)
end = time.time()
print ("Using list : ", round(end-start, 2), end="\n")
给出结果:
Using numpy: 8.35
Using list : 0.02
当使用“追加”时,列表优于numpy?
答案 0 :(得分:1)
回答你的问题,是的。附加到数组是一项昂贵的操作,而列表使其相对便宜(请参阅Internals of Python list, access and resizing runtimes了解原因)。但是,没有理由放弃numpy。还有其他方法可以轻松地将数据添加到numpy数组中。
令人惊讶的是(对我来说,无论如何)有多少方法可以做到这一点。跳到底部查看每个基准测试的基准。
可能最常见的是简单地预先分配数组,并将其编入索引,
$position
当然,您也可以为列表预先分配内存,因此请将其包含在基准比较中。
#using preallocated numpy
start = time.time()
array = np.zeros(N)
for i in range(N):
array[i] = i
end = time.time()
print ("Using preallocated numpy: ", round(end-start, 5), end="\n")
根据你的代码,使用numpy的#using preallocated list
start = time.time()
res = [None]*N
for i in range(N):
res[i] = i
res = np.array(res)
end = time.time()
print ("Using preallocated list : ", round(end-start, 5), end="\n")
函数也可能会有所帮助,该函数使用迭代器的结果来初始化数组。
fromiter
当然,使用内置迭代器并不是非常灵活,所以让我们尝试一下自定义迭代器,
#using numpy fromiter shortcut
start = time.time()
res = np.fromiter(range(N), dtype='float64') # Use same dtype as other tests
end = time.time()
print ("Using fromiter : ", round(end-start, 5), end="\n")
这是使用#using custom iterator
start = time.time()
def it(N):
i = 0
while i < N:
yield i
i += 1
res = np.fromiter(it(N), dtype='float64') # Use same dtype as other tests
end = time.time()
print ("Using custom iterator : ", round(end-start, 5), end="\n")
的两种非常灵活的方式。第一种是使用预分配阵列,是最灵活的。让我们看看他们如何比较:
numpy
关闭,您可以看到预分配使Using numpy: 2.40017
Using list : 0.0164
Using preallocated numpy: 0.01604
Using preallocated list : 0.01322
Using fromiter : 0.00577
Using custom iterator : 0.01458
比使用列表快得多,尽管预分配列表会使两者的速度大致相同。尽管迭代器性能很好,但使用内置迭代器非常快
当使用自定义迭代器时,回退到预分配数组的范围内并列出。
将代码直接转换为numpy
的效果通常不如numpy
。使用append
方法找到方法几乎总能带来实质性的改进。在这种情况下,预先分配数组或将每个元素的计算表示为迭代器,以获得与python列表类似的性能。或者使用vanilla python列表,因为性能大致相同。
编辑:原始答案还包括numpy
。这被删除,因为它不适合一次添加一个元素的用例,np.fromfunction
实际初始化数组并使用fromfunction
的广播进行单个函数调用。它快了大约一百倍,所以如果你能用广播来解决你的问题,请不要理会这些其他方法。