np.array([1,2,3])
我有一个numpy数组。我想将它转换为一个每个1:1排列的元组的numpy数组。像这样:
np.array([
[(1,1),(1,2),(1,3)],
[(2,1),(2,2),(2,3)],
[(3,1),(3,2),(3,3)],
])
有没有关于如何高效地完成这个操作的想法?我需要执行几百万次。
np.array([1,2,3])
np.array([
[(1,1),(1,2),(1,3)],
[(2,1),(2,2),(2,3)],
[(3,1),(3,2),(3,3)],
])
你可以这样做:
>>> a = np.array([1, 2, 3])
>>> n = a.size
>>> np.vstack((np.repeat(a, n), np.tile(a, n))).T.reshape(n, n, 2)
array([[[1, 1],
[1, 2],
[1, 3]],
[[2, 1],
[2, 2],
[2, 3]],
[[3, 1],
[3, 2],
[3, 3]]])
或者,就像Jaime建议的那样,如果我们在这里利用广播,可以获得大约10倍的加速:
>>> a = np.array([1, 2, 3])
>>> n = a.size
>>> perm = np.empty((n, n, 2), dtype=a.dtype)
perm[..., 0] = a[:, None]
perm[..., 1] = a
...
>>> perm
array([[[1, 1],
[1, 2],
[1, 3]],
[[2, 1],
[2, 2],
[2, 3]],
[[3, 1],
[3, 2],
[3, 3]]])
计时比较:
>>> a = np.array([1, 2, 3]*100)
>>> %%timeit
np.vstack((np.repeat(a, n), np.tile(a, n))).T.reshape(n, n, 2)
...
1000 loops, best of 3: 934 µs per loop
>>> %%timeit
perm = np.empty((n, n, 2), dtype=a.dtype)
perm[..., 0] = a[:, None]
perm[..., 1] = a
...
10000 loops, best of 3: 111 µs per loop
如果你正在使用numpy,不要使用元组。利用它的能力并添加另一个大小为2的维度。我的建议是:
x = np.array([1,2,3])
np.vstack(([np.vstack((x, x, x))], [np.vstack((x, x, x)).T])).T
或者:
im = np.vstack((x, x, x))
np.vstack(([im], [im.T])).T
对于一个普通的数组:
ix = np.vstack([x for _ in range(x.shape[0])])
return np.vstack(([ix], [ix.T])).T
array([[[1, 1],
[1, 2],
[1, 3]],
[[2, 1],
[2, 2],
[2, 3]],
[[3, 1],
[3, 2],
[3, 3]]])
但是作为一个3D矩阵,当你看到它的形状时:
Out[25]: (3L, 3L, 2L)
随着数组大小的增加,这种方法比使用排列的解决方案更高效。对于大小为100的数组,我的解决方案需要1毫秒,而使用排列的解决方案则需要46毫秒。@AshwiniChaudhary的解决方案更加高效。
使用 numpy.meshgrid
的另一种方法。
>>> x = np.array([1, 2, 3])
>>> perms = np.stack(np.meshgrid(x, x))
>>> perms
array([[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3]]])
>>> perms.transpose().reshape(9, 2)
array([[1, 1],
[1, 2],
[1, 3],
[2, 1],
[2, 2],
[2, 3],
[3, 1],
[3, 2],
[3, 3]])
itertools.product
获取排列组合,然后将结果转换为 numpy
数组。>>> from itertools import product
>>> p=list(product(a,repeat=2))
>>> np.array([p[i:i+3] for i in range(0,len(p),3)])
array([[[1, 1],
[1, 2],
[1, 3]],
[[2, 1],
[2, 2],
[2, 3]],
[[3, 1],
[3, 2],
[3, 3]]])
np.array(p).reshape(3, 3, 2)
呢? - Billnp.indices
非常优雅地完成这个任务,它可以用来生成一组索引以索引原始数组:>>> x = np.array([1, 2, 3])
>>> i = np.indices((3, 3)).reshape(2, -1)
>>> a[i].T
array([[1, 1],
[1, 2],
[1, 3],
[2, 1],
[2, 2],
[2, 3],
[3, 1],
[3, 2],
[3, 3]])
n
为每个排列中的项目数。n = 5
x = np.arange(10)
i = np.indices([x.size for _ in range(n)]).reshape(n, -1)
a = x[i].T
perm = np.empty((n, n, 2), dtype=a.dtype); perm[..., 0] = a; perm[..., 1] = a[:. None]
- Jaime