在Matlab排序中从numpy数组中顺序获取数据

时间:2017-01-06 14:05:10

标签: python matlab numpy

作为一个例子,假设在Matlab中,像这样的矩阵a(2,3,2)

a(:,:,1) =

     1     2     3
     4     5     6


a(:,:,2) =

     7     8     9
    10    11    12

如果我使用mex并按顺序访问此矩阵的元素,我会得到以下顺序(最后,顺序访问它们的代码):

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

现在,如果我在numpy中有相同的矩阵

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

       [[ 7,  8,  9],
        [10, 11, 12]]])

,我可以尝试使用.flatten(...)按顺序访问项目(无法找到更好的方法 - 我愿意接受建议)。 flatten()有4"命令"选项:

In [4]: a.flatten('F')
Out[4]: array([ 1,  7,  4, 10,  2,  8,  5, 11,  3,  9,  6, 12])

In [5]: a.flatten('C')
Out[5]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

In [6]: a.flatten('A')
Out[6]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

In [7]: a.flatten('K')
Out[7]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

在Matlab排序中是否有一种优雅的方式来访问numpy数组的元素? (在我的实际使用案例中,这些矩阵很大,因此将它们复制在一起并不是首选)

附录:按顺序打印矩阵的代码

[不太好,我知道,只是为了测试]

  1 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  2 {
  3         // This just a test: hardcoding the size of `data_input`
  4         int data_input_size = 12;
  5         double *data_input;
  6         const mxArray *batch_data;
  7 
  8         // Gets a pointer to the first element of batch_data
  9         data_input  = mxGetPr(prhs[0]);
 10 
 11         for(int i = 0; i < data_input_size; i++) {
 12                 printf("working_data[i]: %f\n", data_input[i]);
 13         }
 14         plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
 15 }

2 个答案:

答案 0 :(得分:6)

这会让很多人从MATLAB进入NumPy / Python。因此,在MATLAB中,索引格式为(column x row x dim3),依此类推。使用NumPy,它是(axis-0, axis-1, axis-2),依此类推。

使用MATLAB上的示例案例示意性地显示:

>> a = reshape(1:27,[3,3,3]);
>> a
a(:,:,1) =

        row
    --------------->
     1     4     7   |         |
     2     5     8   | col     |
     3     6     9   v         |
a(:,:,2) =                     |
    10    13    16             | dim3
    11    14    17             |
    12    15    18             |
a(:,:,3) =                     |
    19    22    25             |
    20    23    26             |
    21    24    27             v

On NumPy:

In [62]: a = np.arange(27).reshape(3,3,3)

In [63]: a
Out[63]: 

            axis=2
         ---------->
array([[[ 0,  1,  2],   |          |
        [ 3,  4,  5],   | axis=1   |
        [ 6,  7,  8]],  v          |
                                   |
       [[ 9, 10, 11],              |
        [12, 13, 14],              | axis=0
        [15, 16, 17]],             |
                                   |
       [[18, 19, 20],              |
        [21, 22, 23],              |
        [24, 25, 26]]])            v

让我们尝试关联这两个环境之间问题中列出的3D数组案例的维度和轴术语:

MATLAB      NumPy
------------------
cols        axis-1
rows        axis-2
dim3        axis-0

因此,为了模拟NumPy中与MATLAB相同的行为,我们需要NumPy中的轴为:(1,2,0)。与NumPy一样,从最后一个轴开始存储元素到第一个轴的方式,即按相反的顺序,所需的轴顺序为(0,2,1)

要以这种方式执行轴的置换,我们可以使用np.transpose,然后使用np.ravel() -

进行展平操作
a.transpose(0,2,1).ravel()

示例运行 -

In [515]: a
Out[515]: 
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

In [516]: a.transpose(0,2,1) # Permute axes
Out[516]: 
array([[[ 1,  4],
        [ 2,  5],
        [ 3,  6]],

       [[ 7, 10],
        [ 8, 11],
        [ 9, 12]]])

In [517]: a.transpose(0,2,1).ravel() # Flattened array
Out[517]: array([ 1,  4,  2,  5,  3,  6,  7, 10,  8, 11,  9, 12])

答案 1 :(得分:2)

这是@Divakar's回答的补充。

在Octave中,我制作了xa并将其保存到文件

>> x=[1, 4, 2, 5, 3, 6, 7, 10, 8, 11, 9, 12]
>> a=reshape(x,2,3,2)

a =

ans(:,:,1) =

   1   2   3
   4   5   6

ans(:,:,2) =

    7    8    9
   10   11   12

我可以使{与a相同)展开mex

>> a(:).'

numpy,来自loadmat

scipy.io
In [564]: data = loadmat('test.mat')
In [566]: data['x']
Out[566]: 
array([[  1.,   4.,   2.,   5.,   3.,   6.,   7.,  10.,   8.,  11.,   9.,
         12.]])
In [567]: data['a']
Out[567]: 
array([[[  1.,   7.],
        [  2.,   8.],
        [  3.,   9.]],

       [[  4.,  10.],
        [  5.,  11.],
        [  6.,  12.]]])

ravel订单&#39; F&#39;显示原始广告x

In [571]: data['a'].ravel(order='F')
Out[571]: 
array([  1.,   4.,   2.,   5.,   3.,   6.,   7.,  10.,   8.,  11.,   9., 12.])

为了帮助跟踪形状,我更喜欢使它们变得不同。例如

>> x=0:23;
>> a=reshape(x,2,3,4);

a显示为

ans(:,:,1) =

   0   2   4
   1   3   5
...
ans(:,:,4) =

   18   20   22
   19   21   23

显示4(2,3)个矩阵。

在numpy方面,我得到:

In [575]: data['a'].shape
Out[575]: (2, 3, 4)
In [577]: data['a']
Out[577]: 
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.]]])

这是2块(3,4)形状。

In [579]: data['a'].ravel('F')
Out[579]: 
array([  0.,   1.,   2.,   3.,   4.,   5.,   ...,  23.])

我看到numpy和MATLAB / Octave之间的两个关键区别。默认顺序不同,但numpy允许您指定F。 3d(和更大)数组的显示是不同的。实际上有一种不同的“飞机”概念。或块。

np.transpose更改数组的形状,步幅和顺序,同时保持相同的数据库。

应用于a,它会生成一个带有顺序的(4,3,2)数组&#39; C&#39;:

In [580]: data['a'].T
Out[580]: 
array([[[  0.,   1.],
        [  2.,   3.],
        [  4.,   5.]],

 ....
       [[ 18.,  19.],
        [ 20.,  21.],
        [ 22.,  23.]]])
In [581]: data['a'].T.ravel()
Out[581]: 
array([  0.,   1.,   2.,   3., ...22.,  23.])

MATLAB显示可以复制:

In [584]: for i in range(4):
     ...:     print(data['a'][:,:,i])
     ...:     
[[ 0.  2.  4.]
 [ 1.  3.  5.]]
[[  6.   8.  10.]
 [  7.   9.  11.]]
[[ 12.  14.  16.]
 [ 13.  15.  17.]]
[[ 18.  20.  22.]
 [ 19.  21.  23.]]