【问题标题】:Reshaping 3D numpy array for MATLAB requirement compatibility重塑 3D numpy 数组以实现 MATLAB 要求兼容性
【发布时间】:2021-12-05 09:44:14
【问题描述】:

给定一个形状数组3,2,2

np.array([[[1,2],[3,4]],[[5,6],[7,8]],[[9,10],[11,12]]])

我想把它重塑成2,2,3的形状。

在下游,这个 reshape 数据将在 MATLAB 中处理,并且由于某种原因,MATLAB-Package 要求对数组进行整形2,2,3

在 MATLAB 中,预期的输出应该是

val(:,:,1) =

     1     2
     3     4


val(:,:,2) =

     5     6
     7     8


val(:,:,3) =

     9    10
    11    12

简单地重塑 arr.reshape(2,2,3) 并不会产生我想要的效果。

更新: @hpaulj 提案产生

val(:,:,1) =

   1   3
   2   4


val(:,:,2) =

   5   7
   6   8


val(:,:,3) =

    9   11
   10   12

【问题讨论】:

  • arr.reshape(2,2,3) 产生了什么,为什么会出错?
  • 也可以使用order。 Reshape 不足以匹配 numpy 和 matlab
  • 您将如何传输阵列? scipy.io.savemat 可以进行所需的转换。
  • 感谢@hpaulj,我计划使用 np.save 功能
  • 你会如何用 Matlab 阅读它?

标签: python numpy reshape


【解决方案1】:

我相信您正在寻找:

np.moveaxis(x, 0, 2)

您的原始形状是 (3, 2, 2)。这条线移动axis[0]并将其滚动到axis[2](将其他2个轴向左移动)。所以你得到:

>>> x[:, :, 0]
array([[1, 2],
       [3, 4]])

【讨论】:

  • 我没有 matlab 来实际测试这一点,但如果这不起作用,那么您可能需要切换两个“2”维度。您可以使用 np.swapaxes(x, 0, 2) 来实现这一点(这将简单地将轴 [0] 切换为轴 [2] 而无需移动任何东西)
【解决方案2】:
In [29]: arr = np.array([[[1,2],[3,4]],[[5,6],[7,8]],[[9,10],[11,12]]])
In [30]: arr
Out[30]: 
array([[[ 1,  2],
        [ 3,  4]],

       [[ 5,  6],
        [ 7,  8]],

       [[ 9, 10],
        [11, 12]]])
In [31]: arr.shap
Out[31]: (3, 2, 2)

MATLAB 存储矩阵,如 numpy 的 order 'F',尾随维度最外层。使用 2d 作为转置最容易将其可视化。让我们在 3d 上尝试一下:

In [32]: arr1 = arr.T
In [33]: arr1.shape
Out[33]: (2, 2, 3)
In [34]: arr1
Out[34]: 
array([[[ 1,  5,  9],
        [ 3,  7, 11]],

       [[ 2,  6, 10],
        [ 4,  8, 12]]])

MATLAB 通过迭代最后一维,即其“平面”来显示 3d 数组:

In [36]: for i in range(3):print(arr1[:,:,i])
[[1 3]
 [2 4]]
[[5 7]
 [6 8]]
[[ 9 11]
 [10 12]]

我没有你的 MATLAB npy 加载器,但可以探索io.savemat/loadmat 是如何进行传输的。这适用于 MATLAB 格式的文件:

In [37]: from scipy import io
In [38]: io.savemat('test3d.mat',{'arr':arr, 'arr1':arr1})
In [39]: io.loadmat('test3d.mat')
Out[39]: 
{'__header__': b'MATLAB 5.0 MAT-file Platform: posix, Created on: Sun Dec  5 08:29:25 2021',
 '__version__': '1.0',
 '__globals__': [],
 'arr': array([[[ 1,  2],
         [ 3,  4]],
 
        [[ 5,  6],
         [ 7,  8]],
 
        [[ 9, 10],
         [11, 12]]]),
 'arr1': array([[[ 1,  5,  9],
         [ 3,  7, 11]],
 
        [[ 2,  6, 10],
         [ 4,  8, 12]]])}

在 Octave 会话中:

>> load test3d.mat
>> arr
arr =

ans(:,:,1) =

   1   3
   5   7
   9  11

ans(:,:,2) =

   2   4
   6   8
  10  12

>> arr1
arr1 =

ans(:,:,1) =

   1   3
   2   4

ans(:,:,2) =

   5   7
   6   8

ans(:,:,3) =

   9  11
  10  12

并且分解显示显示转置保留了原始numpy 数据值顺序:

>> arr1(:)'
ans =

   1   2   3   4   5   6   7   8   9  10  11  12

>> arr(:)'
ans =

   1   5   9   3   7  11   2   6  10   4   8  12

另一种转置将 3 移到末尾,但在前 2 中保持顺序

In [40]: arr2 = arr.transpose(1,2,0)
In [41]: arr2
Out[41]: 
array([[[ 1,  5,  9],
        [ 2,  6, 10]],

       [[ 3,  7, 11],
        [ 4,  8, 12]]])
In [42]: for i in range(3):print(arr2[:,:,i])
[[1 2]
 [3 4]]
[[5 6]
 [7 8]]
[[ 9 10]
 [11 12]]

【讨论】:

  • 感谢 savemat,这消除了 MATLAB 中对 3rd 方扩展的需要。
  • 根据您的建议,在 octave 会话中,1,2,3,4 是坐标 (0,0) ,(0,1),(1,0),( 1,1),分别。但是,如果希望将 1,2,3,4 分别定位在 (0,0) ,(1,0),(0,1),(1,1) 中怎么办。我已更新 OP 以反映此要求。谢谢@hpaulj
猜你喜欢
  • 2016-02-10
  • 2017-11-11
  • 2018-03-17
  • 2017-09-18
  • 2020-04-22
  • 2016-05-22
  • 2019-07-10
  • 2021-03-21
  • 2021-10-28
相关资源
最近更新 更多