numpy数组到置换矩阵

时间:2014-12-05 19:41:43

标签: python arrays performance numpy permutation

np.array([1,2,3])

我有一个numpy数组。我想把它变成一个numpy数组,每个1:1排列的元组。像这样:

np.array([
    [(1,1),(1,2),(1,3)],
    [(2,1),(2,2),(2,3)],
    [(3,1),(3,2),(3,3)],
])

有关如何有效地执行此操作的任何想法?我需要做几百万次这个操作。

5 个答案:

答案 0 :(得分:6)

您可以这样做:

>>> 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]]])

或者suggested by @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

答案 1 :(得分:4)

如果您正在使用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)

这比排列的解决方案更有效,因为数组大小越来越大。我的解决方案针对@ Kasra的时间为1ms,而对于一个100的大小为100的阵列,我的解决方案为46ms。@ AshwiniChaudhary的解决方案虽然效率更高。

答案 2 :(得分:1)

您可以使用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]]])

答案 3 :(得分:0)

使用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]])

答案 4 :(得分:0)

我一直在研究如何更好地做到这一点,而不仅仅是2元组。实际上,可以使用np.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

然后,您可以根据需要将结果重塑为n维数组形式,但通常只要排列就足够了。我没有测试这种方法的性能,但可以肯定的是,本机numpy调用和索引应该很快。在我看来,至少这比其他解决方案更为优雅。这与@Bill提供的meshgrid解决方案非常相似。