将itertools数组转换为numpy数组

时间:2015-10-22 13:37:11

标签: python numpy itertools

我正在创建这个数组:

A=itertools.combinations(range(6),2)

我必须用numpy来操作这个数组,比如:

A.reshape(..

如果尺寸A为高,则命令list(A)太慢。

我如何"转换"一个itertools数组到一个numpy数组?

更新1: 我已经尝试过hpaulj的解决方案,在这种特定的情况下有点慢,任何想法?

start=time.clock()

A=it.combinations(range(495),3)
A=np.array(list(A))
print A

stop=time.clock()
print stop-start
start=time.clock()

A=np.fromiter(it.chain(*it.combinations(range(495),3)),dtype=int).reshape (-1,3)
print A

stop=time.clock()
print stop-start

结果:

[[  0   1   2]
 [  0   1   3]
 [  0   1   4]
 ..., 
 [491 492 494]
 [491 493 494]
 [492 493 494]]
10.323822
[[  0   1   2]
 [  0   1   3]
 [  0   1   4]
 ..., 
 [491 492 494]
 [491 493 494]
 [492 493 494]]
12.289898

2 个答案:

答案 0 :(得分:3)

我正在重新打开这个,因为我不喜欢链接的答案。接受的答案建议使用

np.array(list(A))  # producing a (15,2) array

但OP显然已经尝试list(A),并发现它很慢。

另一个答案建议使用np.fromiter。但其评论中隐含的是fromiter需要1d数组的注释。

In [102]: A=itertools.combinations(range(6),2)
In [103]: np.fromiter(A,dtype=int)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-103-29db40e69c08> in <module>()
----> 1 np.fromiter(A,dtype=int)

ValueError: setting an array element with a sequence.

所以在这个itertools中使用fromiter需要以某种方式展平迭代器。

快速的时间安排表明list不是缓慢的步骤。它将列表转换为一个缓慢的数组:

In [104]: timeit itertools.combinations(range(6),2)
1000000 loops, best of 3: 1.1 µs per loop
In [105]: timeit list(itertools.combinations(range(6),2))
100000 loops, best of 3: 3.1 µs per loop
In [106]: timeit np.array(list(itertools.combinations(range(6),2)))
100000 loops, best of 3: 14.7 µs per loop

我认为使用fromiter的最快方法是使用惯用法combinations来展平itertools.chain

In [112]: timeit
np.fromiter(itertools.chain(*itertools.combinations(range(6),2)),dtype=int)
   .reshape(-1,2)
100000 loops, best of 3: 12.1 µs per loop

节省的时间不多,至少在这么小的尺寸上。 (fromiter也需要count,这会削弱另一个μs。对于较大的案例range(60)fromiterarray的一半时间。< / p>

快速搜索[numpy] itertools会产生一些关于生成所有组合的纯粹numpy方式的建议。 itertools很快,用于生成纯Python结构,但将它们转换为数组是一个很慢的步骤。

关于这个问题的挑剔点。

A是一个生成器,而不是一个数组。 list(A)确实生成了一个嵌套列表,可以将其松散地描述为数组。但它不是np.array,也没有reshape方法。

答案 1 :(得分:1)

获取N元素的每个成对组合的另一种方法是使用(N, N)生成np.triu_indices(N, k=1)矩阵的上三角形的索引,例如:

np.vstack(np.triu_indices(6, k=1)).T

对于小型数组,itertools.combinations将获胜,但对于大型 N triu_indices技巧可以大大加快:

In [1]: %timeit np.fromiter(itertools.chain.from_iterable(itertools.combinations(range(6), 2)), np.int)
The slowest run took 10.46 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 4.04 µs per loop

In [2]: %timeit np.array(np.triu_indices(6, 1)).T
The slowest run took 10.97 times longer than the fastest. This could mean that an intermediate result is being cached 
10000 loops, best of 3: 22.3 µs per loop

In [3]: %timeit np.fromiter(itertools.chain.from_iterable(itertools.combinations(range(1000), 2)), np.int)
10 loops, best of 3: 69.7 ms per loop

In [4]: %timeit np.array(np.triu_indices(1000, 1)).T
100 loops, best of 3: 10.6 ms per loop