Python numpy ndarray 索引排列在所有维度(可变维度数)



'M' 是一个 numpy ndarray,其维度 'dim' 数字是可变的(以前生成(,但每个维度的大小 'size' 相等。在我的代码中,它更像是dim = 5,size = 7。

例如:(暗光 = 3,大小 = 4(。

M = np.arange(size**dim).reshape((size,)*dim)
[[[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]
[12 13 14 15]]
[[16 17 18 19]
[20 21 22 23]
[24 25 26 27]
[28 29 30 31]]
[[32 33 34 35]
[36 37 38 39]
[40 41 42 43]
[44 45 46 47]]
[[48 49 50 51]
[52 53 54 55]
[56 57 58 59]
[60 61 62 63]]]

我有一个自己的排列生成器"per",它生成范围(大小(的特定排列(非随机(。

print(next(per))
(1,0,3,2)

我的需要:变换 M,根据我需要的任意数量的排列移动其元素。在示例中:21(第一维为 1 个排列,第二维为 4 个,第三维为 16 个 - 广义:范围(dim( 排列中 d 的大小**d(。我的排列不是随机的,但它们是独立的,彼此不同。

结果可能是:

[[[36 39 37 38]
[33 34 32 35]
[46 44 45 47]]
[41 43 40 42]
[[9  10 11 8]
[2  1  3  0]
[6  7  5  4]
[13 12 14 15]]
[[56 59 57 58]
[63 61 62 60]
[53 54 52 55]
[51 50 49 48]]
[[28 30 29 31]
[27 25 24 26]
[17 18 16 19]
[23 21 20 22]]]

我如何直接从 M 作为 numpy 数组来做到这一点,而我的代码保持动态?

这是广播中的练习:

>>> import numpy as np
>>> from itertools import islice
>>> 
>>> A = np.arange(27).reshape(3,3,3)
>>> def per(n):
...     while True:
...         yield np.random.permutation(n)
... 
>>> pg = per(3)
>>> 
>>> p0 = next(pg)[..., None, None]
>>> p1 = np.array([p for p in islice(pg, 3)])[..., None]
>>> p2 = np.array([[p for p in islice(pg, 3)] for _ in range(3)])
>>> 
>>> p0
array([[[2]],
[[1]],
[[0]]])
>>> p1
array([[[1],
[0],
[2]],
[[1],
[0],
[2]],
[[0],
[2],
[1]]])
>>> p2
array([[[1, 0, 2],
[0, 2, 1],
[0, 1, 2]],
[[2, 1, 0],
[1, 2, 0],
[2, 1, 0]],
[[1, 2, 0],
[2, 1, 0],
[2, 1, 0]]])
>>> A[p0, p1, p2]
array([[[22, 21, 23],
[18, 20, 19],
[24, 25, 26]],
[[14, 13, 12],
[10, 11,  9],
[17, 16, 15]],
[[ 1,  2,  0],
[ 8,  7,  6],
[ 5,  4,  3]]])

一般解决方案:

import numpy as np
from itertools import islice
def per(n=None):
while True:
n = (yield n if n is None else np.random.permutation(n)) or n
def sweep(shp):
pg = per()
pg.send(None)
redshp = len(shp)*[1]
sz = 1
for j, k in enumerate(shp):
pg.send(k)
redshp[j] = k
yield np.reshape((*islice(pg, sz),), redshp)
sz *= k
# example
a = np.arange(24).reshape((2,3,4))
idx = *sweep(a.shape),
for i in idx:
print(i)
print(a[idx])

多亏了保罗·潘泽的精彩回答,我设法解决了这个问题。 保罗的最后一个答案很棒,而且完全是广义的(即使有非平方矩阵! 我最初的问题不太笼统,因为我的目标是让我的全维排列适用于平方矩阵。我简化并缩短了代码,所以我在这里分享它:

import numpy as np
from itertools import islice,count
size,dim = 4,3
per = (np.random.permutation(size) for _ in count())
idx = *(np.reshape((*islice(per, size**d),),[size]*(d+1)+[1]*(dim-d-1)) for d in range(dim)),
a = np.arange(size**dim).reshape((size,)*dim)
print(a[idx])

最新更新