Изменение размеров массива numpy

Я хотел бы сделать следующее:

for i in dimension1:
  for j in dimension2:
    for k in dimension3:
      for l in dimension4:
        B[k,l,i,j] = A[i,j,k,l]

без использования петель. В конце оба А и В содержат ту же информацию, но индексируют иначе.

Я должен указать, что размеры 1,2,3 и 4 могут быть одинаковыми или разными. Поэтому numpy.reshape() кажется сложным.

Ответы

Ответ 1

Обратите внимание: ответ Хайме лучше. NumPy обеспечивает np.transpose именно для этой цели.


Или используйте np.einsum; это, возможно, извращение по назначению, но синтаксис довольно приятный:

In [195]: A = np.random.random((2,4,3,5))

In [196]: B = np.einsum('klij->ijkl', A)

In [197]: A.shape
Out[197]: (2, 4, 3, 5)

In [198]: B.shape
Out[198]: (3, 5, 2, 4)

In [199]: import itertools as IT    
In [200]: all(B[k,l,i,j] == A[i,j,k,l] for i,j,k,l in IT.product(*map(range, A.shape)))
Out[200]: True

Ответ 2

Канонический способ сделать это в numpy будет использовать np.transpose необязательный аргумент перестановки. В вашем случае, чтобы перейти от ijkl в klij, перестановка равна (2, 3, 0, 1), например:

In [16]: a = np.empty((2, 3, 4, 5))

In [17]: b = np.transpose(a, (2, 3, 0, 1))

In [18]: b.shape
Out[18]: (4, 5, 2, 3)

Ответ 3

Вы можете rollaxis дважды:

>>> A = np.random.random((2,4,3,5))
>>> B = np.rollaxis(np.rollaxis(A, 2), 3, 1)
>>> A.shape
(2, 4, 3, 5)
>>> B.shape
(3, 5, 2, 4)
>>> from itertools import product
>>> all(B[k,l,i,j] == A[i,j,k,l] for i,j,k,l in product(*map(range, A.shape)))
True

или, может быть, swapaxes дважды:

>>> A = np.random.random((2,4,3,5))
>>> C = A.swapaxes(0, 2).swapaxes(1,3)
>>> C.shape
(3, 5, 2, 4)
>>> all(C[k,l,i,j] == A[i,j,k,l] for i,j,k,l in product(*map(range, A.shape)))
True

Ответ 4

Я бы посмотрел на numpy.ndarray.shape и itertools.product:

import numpy, itertools
A = numpy.ones((10,10,10,10))
B = numpy.zeros((10,10,10,10))

for i, j, k, l in itertools.product(*map(xrange, A.shape)):
    B[k,l,i,j] = A[i,j,k,l]

Под "без использования циклов" я предполагаю, что вы подразумеваете "без использования вложенных циклов", конечно. Если не существует какой-то встроенной функции numpy, я думаю, что это ваш лучший выбор.