python - 编写一个在 matlab 中可读的 3d numpy 数组

标签 python arrays matlab numpy

我正在尝试将 3D numpy 数组保存到我的磁盘,以便以后可以在 matlab 中读取它。我在 3D 数组上使用 numpy.savetxt() 时遇到了一些困难,所以我的解决方案是首先使用以下代码将其转换为 1D 数组:

import numpy

array = numpy.array([[0, 1, 2, 3],
       [0, 1, 1, 3],
       [3, 1, 3, 1]])

ndarray = numpy.dstack((array, array, array))

darray = ndarray.reshape(36,1)

numpy.savetxt('test.txt', darray, fmt = '%i')

然后在matlab中可以用下面的代码读取:

file = fopen('test.txt')
array = fscanf(file, '%f')

我现在的问题是将其转换回原始形状。使用 reshape(array, 3,4,3) 产生以下结果:

ans(:,:,1) =

     0     1     2     3
     0     1     2     3
     0     1     2     3


ans(:,:,2) =

     0     1     1     3
     0     1     1     3
     0     1     1     3


ans(:,:,3) =

     3     1     3     1
     3     1     3     1
     3     1     3     1

我尝试转置一维 matlab 数组,然后使用 reshape() 但得到相同的数组。

我可以应用什么 matlab 函数来实现我的原始 python 数组?

最佳答案

您想置换维度。在 numpy 中,这是 transpose。有两种复杂情况 - MATLAB 矩阵的“F”阶和显示模式,使用最后一个维度上的 block (这是具有 F 阶的外部维度)。跳转到此答案的末尾以了解详细信息。

===

In [72]: arr = np.array([[0, 1, 2, 3],
    ...:        [0, 1, 1, 3],
    ...:        [3, 1, 3, 1]])
    ...:        
In [80]: np.dstack((arr,arr+1))
Out[80]: 
array([[[0, 1],
        [1, 2],
        [2, 3],
        [3, 4]],

       [[0, 1],
        [1, 2],
        [1, 2],
        [3, 4]],

       [[3, 4],
        [1, 2],
        [3, 4],
        [1, 2]]])
In [81]: np.dstack((arr,arr+1)).shape
Out[81]: (3, 4, 2)

In [75]: from scipy.io import loadmat, savemat
In [76]: pwd
Out[76]: '/home/paul/mypy'
In [83]: savemat('test3',{'arr':arr, 'arr3':arr3})

Octave 音阶

>> load 'test3.mat'
>> arr
arr =

  0  1  2  3
  0  1  1  3
  3  1  3  1

>> arr3
arr3 =

ans(:,:,1) =

  0  1  2  3
  0  1  1  3
  3  1  3  1

ans(:,:,2) =

  1  2  3  4
  1  2  2  4
  4  2  4  2

>> size(arr3)
ans =

   3   4   2

回到 numpy 我可以将数组显示为 2 个 3x4 block :

In [95]: arr3[:,:,0]
Out[95]: 
array([[0, 1, 2, 3],
       [0, 1, 1, 3],
       [3, 1, 3, 1]])
In [96]: arr3[:,:,1]
Out[96]: 
array([[1, 2, 3, 4],
       [1, 2, 2, 4],
       [4, 2, 4, 2]])

这些数组,拼成 1d(实际上显示了底层数据缓冲区中值的布局):

In [100]: arr.ravel()
Out[100]: array([0, 1, 2, 3, 0, 1, 1, 3, 3, 1, 3, 1])
In [101]: arr3.ravel()
Out[101]: 
array([0, 1, 1, 2, 2, 3, 3, 4, 0, 1, 1, 2, 1, 2, 3, 4, 3, 4, 1, 2, 3, 4, 1, 2])

Octave中对应的ravel:

>> arr(:).'
ans =
  0  0  3  1  1  1  2  1  3  3  3  1

>> arr3(:).'
ans =
  0  0  3  1  1  1  2  1  3  3  3  1  1  1  4  2  2  2  3  2  4  4  4  2

MATLAB 使用 F (fortran) 顺序,第一个维度变化最快。因此显示 block arr(:,:i) 是很自然的。您可以在创建和使用 numpy 数组时指定 order='F'。但是保持顺序正确可能很棘手,尤其是在使用 3d 时。 loadmat/savemat 尝试为我们做一些重新排序。例如,二维 MATLAB 矩阵在 numpy 中加载为顺序 F 数组。


In [107]: np.array([0,0,3,1,1,1,2,1,3,3,3,1])
Out[107]: array([0, 0, 3, 1, 1, 1, 2, 1, 3, 3, 3, 1])
In [108]: np.array([0,0,3,1,1,1,2,1,3,3,3,1]).reshape(4,3)
Out[108]: 
array([[0, 0, 3],
       [1, 1, 1],
       [2, 1, 3],
       [3, 3, 1]])
In [109]: np.array([0,0,3,1,1,1,2,1,3,3,3,1]).reshape(4,3).T
Out[109]: 
array([[0, 1, 2, 3],
       [0, 1, 1, 3],
       [3, 1, 3, 1]])
In [111]: np.array([0,0,3,1,1,1,2,1,3,3,3,1]).reshape((3,4),order='F')
Out[111]: 
array([[0, 1, 2, 3],
       [0, 1, 1, 3],
       [3, 1, 3, 1]])

使用这个数组可能更容易跟踪形状:

In [112]: arr3 = np.arange(2*3*4).reshape(2,3,4)
In [113]: arr3f = np.arange(2*3*4).reshape(2,3,4, order='F')
In [114]: arr3
Out[114]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
In [115]: arr3f
Out[115]: 
array([[[ 0,  6, 12, 18],
        [ 2,  8, 14, 20],
        [ 4, 10, 16, 22]],

       [[ 1,  7, 13, 19],
        [ 3,  9, 15, 21],
        [ 5, 11, 17, 23]]])
In [116]: arr3f.ravel()
Out[116]: 
array([ 0,  6, 12, 18,  2,  8, 14, 20,  4, 10, 16, 22,  1,  7, 13, 19,  3,
        9, 15, 21,  5, 11, 17, 23])
In [117]: arr3f.ravel(order='F')
Out[117]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])
In [118]: savemat('test3',{'arr3':arr3, 'arr3f':arr3f})

Octave :

>> arr3
arr3 =
ans(:,:,1) =
   0   4   8
  12  16  20

ans(:,:,2) =
   1   5   9
  13  17  21
....
>> arr3f
arr3f =
ans(:,:,1) =
   0   2   4
   1   3   5

ans(:,:,2) =
   6   8  10
   7   9  11
...
>> arr3.ravel()'
error: int32 matrix cannot be indexed with .
>> arr3(:)'
ans =
 Columns 1 through 20:
   0  12   4  16   8  20   1  13   5  17   9  21   2  14   6  18  10  22   3  15
 Columns 21 through 24:
   7  19  11  23
>> arr3f(:)'
ans =
 Columns 1 through 20:
   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19
 Columns 21 through 24:
  20  21  22  23

arr3f 在按 block 打印时仍然看起来“一团糟”,但在拼凑时我们看到值是按相同的 F 顺序排列的。如果我们打印 numpy 数组的最后一个“ block ”,这也很明显:

In [119]: arr3f[:,:,0]
Out[119]: 
array([[0, 2, 4],
       [1, 3, 5]])

因此,为了匹配 numpy 和 matlab,我们必须保持两点直截了当 - 顺序和 block 显示样式。

我的 MATLAB 生锈了,但我发现 permutenp.transpose 类似。使用它来重新排序尺寸:

>> permute(arr3,[3,2,1])
ans =
ans(:,:,1) =
   0   4   8
   1   5   9
   2   6  10
   3   7  11

ans(:,:,2) =
  12  16  20
  13  17  21
  14  18  22
  15  19  23
>> permute(arr3,[3,2,1])(:)'
ans =
 Columns 1 through 20:
   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19
 Columns 21 through 24:
  20  21  22  23

numpy 中的等效转置

In [121]: arr3f.transpose(2,1,0).ravel()
Out[121]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])

(很抱歉回答漫无边际。我可能会回去编辑它。希望它能给你一些有用的东西。)

===

让我们尝试更明确地将这种漫无边际的内容应用到您的案例中

In [122]: x = np.array([[0, 1, 2, 3],
     ...:        [0, 1, 1, 3],
     ...:        [3, 1, 3, 1]])
     ...:        
In [123]: x3 = np.dstack((x,x,x))
In [125]: dx3 = x3.reshape(36,1)
In [126]: np.savetxt('test3.txt',dx3, fmt='%i')
In [127]: cat test3.txt
0
0
0
....
3
3
1
1
1

Octave 音阶

>> file = fopen('test3.txt')
file =  21
>> array = fscanf(file,'%f')
array =
   0
   0
   ....

>> reshape(array,3,4,3)
ans =
ans(:,:,1) =
   0   1   2   3
   0   1   2   3
   0   1   2   3
ans(:,:,2) =
   0   1   1   3
   0   1   1   3
   0   1   1   3
ans(:,:,3) =
   3   1   3   1
   3   1   3   1
   3   1   3   1

和排列

>> permute(reshape(array,3,4,3),[3,2,1])
ans =
ans(:,:,1) =
   0   1   2   3
   0   1   1   3
   3   1   3   1
ans(:,:,2) =
   0   1   2   3
   0   1   1   3
   3   1   3   1
ans(:,:,3) =
   0   1   2   3
   0   1   1   3
   3   1   3   1

关于python - 编写一个在 matlab 中可读的 3d numpy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48053572/

相关文章:

ios - 在 Swift 的 TableView 中填充数据时出现问题

multithreading - 在 Octave 中使用线程运行代码

arrays - 关于矩阵运算的问题

python - MIDI 刻度是固定值还是取决于文件的 BPM?

c - bool 数组的排列

javascript - 如何从JS数组中删除不同类型的空值(元素)

arrays - 对于普通的 MATLAB 数组,是否有类似 deal() 的东西?

只有功能的python变量范围

python - 我在哪里可以找到 igraph 布局源代码?

python - F2py 转换字符(*) 段错误