问题
np.array([1,2,3])
I've got numpy array. I would like to turn it into a numpy array with tuples of each 1:1 permutation. Like this:
np.array([
[(1,1),(1,2),(1,3)],
[(2,1),(2,2),(2,3)],
[(3,1),(3,2),(3,3)],
])
Any thoughts on how to do this efficiently? I need to do this operation a few million times.
回答1:
If you're working with numpy, don't work with tuples. Use its power and add another dimension of size two. My recommendation is:
x = np.array([1,2,3])
np.vstack(([np.vstack((x, x, x))], [np.vstack((x, x, x)).T])).T
or:
im = np.vstack((x, x, x))
np.vstack(([im], [im.T])).T
And for a general array:
ix = np.vstack([x for _ in range(x.shape[0])])
return np.vstack(([ix], [ix.T])).T
This will produce what you want:
array([[[1, 1],
[1, 2],
[1, 3]],
[[2, 1],
[2, 2],
[2, 3]],
[[3, 1],
[3, 2],
[3, 3]]])
But as a 3D matrix, as you can see when looking at its shape:
Out[25]: (3L, 3L, 2L)
This is more efficient than the solution with permutations as the array size get's bigger. Timing my solution against @Kasra's yields 1ms for mine vs. 46ms for the one with permutations for an array of size 100. @AshwiniChaudhary's solution is more efficient though.
回答2:
You can do something like this:
>>> 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]]])
Or as suggested by @Jaime you can get around 10x speedup if we take advantage of broadcasting here:
>>> 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]]])
Timing comparisons:
>>> 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
回答3:
You can use itertools.product
to get the permutations , then convert the result to numpy
array.
>>> 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]]])
回答4:
Yet another way using 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]])
来源:https://stackoverflow.com/questions/27323448/numpy-array-to-permutation-matrix