Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 迭代numpy数组的最快方法是什么_Python_Pandas_Numpy_Itertools - Fatal编程技术网

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

Python 迭代numpy数组的最快方法是什么,python,pandas,numpy,itertools,Python,Pandas,Numpy,Itertools,我注意到“直接”遍历numpy数组与通过tolist方法遍历numpy数组之间有一个有意义的区别。见下面的计时: 直接 [np.arange(10000000)中的i代表i] 通过tolist [np.arange(10000000.tolist()]中的i代表i 考虑到我已经发现了一种更快的方法。我想问还有什么能让它跑得更快 迭代numpy数组的最快方法是什么?这其实并不奇怪。让我们从最慢的开始,一次检查一个方法 [i for i in np.arange(10000000)] 此方法要

我注意到“直接”遍历numpy数组与通过
tolist
方法遍历numpy数组之间有一个有意义的区别。见下面的计时:

直接
[np.arange(10000000)中的i代表i]

通过
tolist

[np.arange(10000000.tolist()]中的i代表i


考虑到我已经发现了一种更快的方法。我想问还有什么能让它跑得更快


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

这其实并不奇怪。让我们从最慢的开始,一次检查一个方法

[i for i in np.arange(10000000)]
此方法要求python访问numpy数组(存储在C内存范围中),每次访问一个元素,在内存中分配一个python对象,并在列表中创建指向该对象的指针。每次在存储在C后端的numpy数组之间进行管道传输并将其拉入纯python时,都会产生开销。这种方法增加了10000000倍的成本

下一步:

在本例中,使用
.tolist()
对numpy C后端进行一次调用,并一次性将所有元素分配给列表。然后,您将使用python对该列表进行迭代

最后:

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



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

这些是我在较慢机器上的计时

In [1034]: timeit [i for i in np.arange(10000000)]
1 loop, best of 3: 2.16 s per loop
如果我直接生成范围(Py3,所以这是一个Generator),时间会好得多。将此作为此大小列表理解的基线

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
中的值构造的,而不仅仅是一个获取的值

列表(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
将数组转换为一个纯列表,在本例中为整数列表。它比
list()
做更多的工作,但它是在编译代码中完成的

In [1047]: ll=a.tolist()
In [1048]: type(ll[0])
Out[1048]: int
通常不要使用
list(anarray)
。它很少做任何有用的事情,而且不如
tolist()
强大

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

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

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

但你真正的目标是什么

我的测试用例有一个
numpy数组

[[  34  107]
 [ 963  144]
 [ 921 1187]
 [   0 1149]]
我只使用
范围
枚举

使用范围

结果

使用枚举

结果


我选择的这个测试用例
enumerate
将运行得更快

,这很奇怪。我自己尝试过好几次,似乎把它转换成列表会让它一直更快。谢谢你把这件事公诸于众。只是迭代并获取列表,或者也做一些处理?只使用
list(np.arange(1000000))
看起来相当快。@Divakar我的问题是,为什么要迭代numpy数组而不是使用矢量化函数。
list()
生成
np.int32
对象的列表
tolist
生成
int
的列表。它们不一样。但是
list(np.arange(10))
np.arange(10.tolist()
)之间有一个细微的区别:第一个将产生一个
np.int64
列表,第二个是python
int
s列表。第一种方法在进行序列化(如使用json)时可能会出现问题。json在第一个问题上会出错,因为它无法处理
np.int64
,这非常有用,这就是为什么我对它进行了升级,我希望其他人也这样做。我现在还没有回答这个问题,因为我仍然希望看到通过数组进行迭代的其他选项。谢谢@hpaulj这非常接近于实际回答我的问题,因为你说。。。“遍历数组最快的方法是什么-无。”我可能会选择这个作为我的答案,但我会暂时保留它。
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