Python 交换 numpy 数组的维度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23943379/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 03:43:46  来源:igfitidea点击:

Swapping the dimensions of a numpy array

pythonarraysoptimizationnumpydimensions

提问by sponce

I would like to do the following:

我想做以下事情:

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]

without the use of loops. In the end both A and B contain the same information but indexed differently.

不使用循环。最后,A 和 B 包含相同的信息,但索引不同。

I must point out that the dimension 1,2,3 and 4 can be the same or different. So a numpy.reshape() seems difficult.

我必须指出,维度 1、2、3 和 4 可以相同或不同。所以 numpy.reshape() 似乎很难。

采纳答案by unutbu

Please note: Jaime's answeris better. NumPy provides np.transposeprecisely for this purpose.

请注意:Jaime 的回答更好。NumPynp.transpose正是为此目的而提供的。



Or use np.einsum; this is perhaps a perversion of its intended purpose, but the syntax is quite nice:

或者使用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

回答by metaperture

I would look at numpy.ndarray.shape and itertools.product:

我会看看 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]

By "without the use of loops" I'm assuming you mean "without the use of nested loops", of course. Unless there's some numpy built-in that does this, I think this is your best bet.

当然,“不使用循环”是指“不使用嵌套循环”。除非有一些内置的 numpy 可以做到这一点,否则我认为这是你最好的选择。

回答by DSM

You could rollaxistwice:

你可以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

or maybe swapaxestwice is easier to follow:

或者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

回答by Jaime

The canonical way of doing this in numpy would be to use np.transpose's optional permutation argument. In your case, to go from ijklto klij, the permutation is (2, 3, 0, 1), e.g.:

在 numpy 中执行此操作的规范方法是使用np.transpose的可选排列参数。在您的情况下,从ijklklij,排列是(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)

回答by kmario23

One can also leverage numpy.moveaxis()for movingthe required axes to desired locations. Here is an illustration, stealing the example from Jaime's answer:

人们也可以利用numpy.moveaxis()用于移动所需的轴到所需的位置。这是一个插图,从Jaime 的回答中窃取了示例:

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

# move the axes that are originally at positions [0, 1] to [2, 3]
In [161]: np.moveaxis(a, [0, 1], [2, 3]).shape 
Out[161]: (4, 5, 2, 3)