交换numpy数组的维度

Posted

技术标签:

【中文标题】交换numpy数组的维度【英文标题】:Swapping the dimensions of a numpy array 【发布时间】:2014-07-19 13:14:01 【问题描述】:

我想做以下事情:

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]

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

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

【问题讨论】:

dimension 变量是什么?你错过了一些range 电话吗? 【参考方案1】:

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

【讨论】:

【参考方案2】:

请注意:Jaime's answer 更好。 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

【讨论】:

@DSM - 我认为你获得了“今日糟糕的双关语”奖! 这对我来说是最好的解决方案,因为我实际上有 7 个维度,并且很难进行多次交换或滚动。我实际上虽然关于 einsum 但不知何故以错误的语法使用它并且无法做到。非常感谢 !!!我非常喜欢 einsum 【参考方案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

【讨论】:

+1 在旁注中,product(*map(range, A.shape)) 可以更简洁地写成np.ndindex(*A.shape)【参考方案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 可以做到这一点,否则我认为这是你最好的选择。

【讨论】:

在 NumPy 中,避免循环的一般目标之一是让代码的 C 部分完成繁重的工作。这意味着嵌套循环或itertools.product 都是不可取的。 谢谢超孔径!你有什么建议 user2357112 ?哪个 C 例程可以做到这一点?【参考方案5】:

也可以利用numpy.moveaxis() 将所需的轴移动到所需的位置。这是一个插图,偷了Jaime's answer的例子:

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)

【讨论】:

你能在这里看看我的问题吗:datascience.stackexchange.com/questions/58123/…np.moveaxis() 如何将数组拆分为 r、b、g?我的教练告诉我它是np.split(),但这是用np.movieaxis 隐式调用的吗?

以上是关于交换numpy数组的维度的主要内容,如果未能解决你的问题,请参考以下文章

numpy数组的堆叠:numpy.stack, numpy.hstack, numpy.vstack

Numpy 数组:连接展平和添加维度

Numpy数组维度

Numpy数组随机生成/维度增加/维度转换

如何展平 numpy 数组的最后两个维度? [复制]

向numpy数组添加维度[重复]