什么是迭代numpy数组的最快方法

时间:2016-11-14 16:29:00

标签: python pandas numpy itertools

我注意到在“直接”迭代numpy数组与通过tolist方法迭代之间存在有意义的差异。见下面的时间安排:

直接
[i for i in np.arange(10000000)]
通过tolist
[i for i in np.arange(10000000).tolist()]

enter image description here

考虑到我发现了一种更快的方法。我想问一下还有什么可以让它变得更快?

迭代numpy数组的最快方法是什么?

3 个答案:

答案 0 :(得分:8)

这实际上并不奇怪。让我们一次从最慢的方式检查方法。

[i for i in np.arange(10000000)]

此方法要求python进入numpy数组(存储在C内存作用域中),一次一个元素,在内存中分配Python对象,并在列表中创建指向该对象的指针。每次在C后端存储的numpy数组之间进行管道处理并将其拉入纯python时,都会产生开销。这种方法增加了10,000,000次。

下一步:

[i for i in np.arange(10000000).tolist()]

在这种情况下,使用.tolist()只调用numpy C后端,并将一次性中的所有元素分配给列表。然后,您使用python迭代该列表。

最后:

list(np.arange(10000000))

这基本上与上面的内容相同,但它创建了一个numpy的本机类型对象列表(例如np.int64)。使用list(np.arange(10000000))np.arange(10000000).tolist()几乎应该是同一时间。

因此,就迭代而言,使用numpy的主要优点是您不需要迭代。在阵列上以矢量化方式应用操作。迭代只会减慢速度。如果你发现自己在数组元素上进行迭代,你应该寻找一种方法来重构你正在尝试的算法,这种方式只使用numpy操作(它有很多内置的!)或者如果真的有必要你可以使用np.apply_along_axisnp.apply_over_axisnp.vectorize

答案 1 :(得分:5)

这是我在较慢机器上的时间

In [1034]: timeit [i for i in np.arange(10000000)]
1 loop, best of 3: 2.16 s per loop

如果我直接生成范围(Py3,因此这是一个发明者)时间要好得多。以此为基础,获得此大小的列表理解。

In [1035]: timeit [i for i in range(10000000)]
1 loop, best of 3: 1.26 s per loop

tolist首先将arange转换为列表;需要更长的时间,但迭代仍在列表中

In [1036]: timeit [i for i in np.arange(10000000).tolist()]
1 loop, best of 3: 1.6 s per loop

使用list() - 同时直接迭代数组;这表明直接迭代首先做到这一点。

In [1037]: timeit [i for i in list(np.arange(10000000))]
1 loop, best of 3: 2.18 s per loop

In [1038]: timeit np.arange(10000000).tolist()
1 loop, best of 3: 927 ms per loop

同时迭代.tolist

In [1039]: timeit list(np.arange(10000000))
1 loop, best of 3: 1.55 s per loop

通常,如果必须循环,则在列表上工作会更快。访问列表元素更简单。

查看索引返回的元素。

a[0]是另一个numpy对象;它是根据a中的值构建的,但不仅仅是获取值

list(a)[0]是同一类型;该列表只是[a[0], a[1], a[2]]]

In [1043]: a = np.arange(3)
In [1044]: type(a[0])
Out[1044]: numpy.int32
In [1045]: ll=list(a)
In [1046]: type(ll[0])
Out[1046]: numpy.int32

tolist将数组转换为纯列表,在本例中为int列表。它比list()做更多的工作,但是在编译的代码中做了。

In [1047]: ll=a.tolist()
In [1048]: type(ll[0])
Out[1048]: int

一般情况下,请勿使用list(anarray)。它很少有用,并没有tolist()那么强大。

迭代数组的最快方法是什么 - 无。至少不是在Python中;在c代码中有快速的方法。

a.tolist()是从数组创建列表整数的最快,矢量化方式。它迭代,但在编译的代码中这样做。

但你的真正目标是什么?

答案 2 :(得分:0)

我的测试用例有numpy array

[[  34  107]
 [ 963  144]
 [ 921 1187]
 [   0 1149]]

我只使用rangeenumerate

进行一次此操作
  

使用范围

loopTimer1 = default_timer()
for l1 in range(0,4):
    print(box[l1])
print("Time taken by range: ",default_timer()-loopTimer1)
  

结果

[ 34 107]
[963 144]
[ 921 1187]
[   0 1149]
Time taken by range:  0.0005405639985838206
  

使用枚举

loopTimer2 = default_timer()
for l2,v2 in enumerate(box):
    print(box[l2])
print("Time taken by enumerate: ", default_timer() - loopTimer2)
  

结果

[ 34 107]
[963 144]
[ 921 1187]
[   0 1149]
Time taken by enumerate:  0.00025605700102460105

我选择enumerate的测试用例会更快

相关问题