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

时间:2018-01-01 21:58:25

标签: 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

我试图转置1D matlab数组,然后使用reshape()但获得相同的数组。

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

1 个答案:

答案 0 :(得分:6)

您希望permute尺寸。在numpy中,这是transpose。有两个并发症 - ' F' MATLAB矩阵的顺序和显示模式,使用最后一个维度上的块(具有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块:

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中相应的混乱:

>> 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)顺序,第一维度变化最快。因此,显示块arr(:,:i)是很自然的。您可以在创建和使用order='F'数组时指定numpy。但是保持秩序直截了当可能很棘手,尤其是在使用3d时。 loadmat/savemat尝试为我们做一些重新排序。例如,2d 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看起来仍然是' messedup'当用块打印时,但是当被拉平时,我们看到值是相同的F顺序。如果我们打印最后一个块'那也很明显。 numpy数组:

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

因此,为了匹配numpy和matlab,我们必须保持两件事 - 顺序和块显示样式。

我的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