【发布时间】:2013-08-01 03:54:54
【问题描述】:
我有一长串 xy 坐标,想把它转换成 numpy 数组。
>>> import numpy as np
>>> xy = np.random.rand(1000000, 2).tolist()
显而易见的方法是:
>>> a = np.array(xy) # Very slow...
但是,上面的代码慢得不合理。有趣的是,先转置长列表,将其转换为 numpy 数组,然后转回会快得多(在我的笔记本电脑上是 20 倍)。
>>> def longlist2array(longlist):
... wide = [[row[c] for row in longlist] for c in range(len(longlist[0]))]
... return np.array(wide).T
>>> a = longlist2array(xy) # 20x faster!
这是numpy的bug吗?
编辑:
这是一个动态生成的点列表(带有 xy 坐标),因此我认为当前的表示是最自然的,而不是预先分配一个数组并在必要时扩大它,或者为 x 和 y 维护两个 1D 列表.
既然我们在双向遍历 python 列表,为什么循环第二个索引比第一个索引快?
编辑 2:
根据@tiago 的回答和this question,我发现以下代码的速度是原始版本的两倍:
>>> from itertools import chain
>>> def longlist2array(longlist):
... flat = np.fromiter(chain.from_iterable(longlist), np.array(longlist[0][0]).dtype, -1) # Without intermediate list:)
... return flat.reshape((len(longlist), -1))
【问题讨论】:
-
这不是错误,而是功能!
-
那么这个功能有什么用呢?我唯一能想到的就是检查每个内部列表的长度是否相同,但我认为不会花这么长时间......
-
@herrlich10 列表在内存中不一定是连续的,因此
np.array循环遍历第一个索引(列表索引)并将其添加到数组中。这就是为什么当第一个索引比第二个大得多时需要更长的时间。 -
@tiago 遵循类似的逻辑,内部列表在内存中也可能不连续。为什么循环第二个索引这么快?
标签: python performance numpy