num2cell()的python / numpy等价物是什么?

时间:2016-10-26 15:57:24

标签: python arrays matlab numpy

我不幸的是通过numpy数组将一些MATLAB代码转换为Python。

num2cell()是否有任何共识?

就个人而言,我认为这违反了Python / numpy语法。这个想法是这样的:

使用num2cell,你最终会得到一个看起来像这样的数组

array([[0],[1],[2],[3],[4],[5],[6],[7],[8]])

请参阅the MathWorks documentaiton

你可以在numpy中使用列表理解来完成这个:

matlab_lunacy = np.array([[x] for x in range(0, 9)]

但为什么MATLAB用户使用这种数据结构?

什么是numpy等价物?

5 个答案:

答案 0 :(得分:4)

在过去的好日子里(大约3.0版),MATLAB只有一个数据结构,一个矩阵。它可以包含数字或字符,并且总是2d。

添加单元格以包含更多通用对象,包括矩阵和字符串。他们还是2d。

Python有列表,它们是1d,但可以包含任何内容。 numpy基于Python构建,添加了多维数组。但列表仍然可用。

因此,将数组转换为列表的任何内容都可能等同于num2cell - 不完全相同,但功能重叠。

In [246]: A=np.arange(24).reshape(2,3,4)   # 3d array

包含在列表中,为我们提供了2个数组的列表(2d):

In [247]: B=list(A)
In [248]: B
Out[248]: 
[array([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]]), 
 array([[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]])]

tolist方法执行完全转换为列表(嵌套)。

In [249]: C=A.tolist()
In [250]: C
Out[250]: 
[[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]],
 [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]

list(A)并不常见,并且在tolist出现时可能会出错。

np.split(A,...)B类似,但子数组仍为3d。

unpacking甚至有效,主要是因为A是可迭代的,[a for a in A]在第一维上分割A

In [257]: a,b=A
In [258]: a
Out[258]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

有一个对象dtype,允许您将对象(包括其他数组)放入数组中。但正如许多SO问题所示,构建这些问题可能很棘手。 np.array尝试构造可能的最高维数组。你必须采取一些技巧来解决这个问题。

In [259]: Z=np.empty((2,),dtype=object)
In [260]: Z
Out[260]: array([None, None], dtype=object)
In [261]: Z[0]=A[0]
In [262]: Z[1]=A[1]
In [263]: Z
Out[263]: 
array([ array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]]),
       array([[12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])], dtype=object)

=====

在Octave会议中:

>> anum = [1,2,3,4]
anum =

   1   2   3   4

>> acell = num2cell(anum)
acell =
{
  [1,1] =  1
  [1,2] =  2
  [1,3] =  3
  [1,4] =  4
}
>> save -7 test.mat anum acell

scipy.io.loatmat

In [1822]: data = io.loadmat('../test.mat')
In [1823]: data
Out[1823]: 
{'__globals__': [],
 '__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.0.0, 
     2016-10-27 00:59:27 UTC',
 '__version__': '1.0',
 'acell': array([[array([[ 1.]]), array([[ 2.]]), array([[ 3.]]),
      array([[ 4.]])]], dtype=object),
 'anum': array([[ 1.,  2.,  3.,  4.]])}

matrix呈现为2d数组; cell作为对象类型数组(2d),在本例中包含2d数组。

答案 1 :(得分:2)

num2cell基本上将每个元素放在一个数组中,并将其作为单元格矩阵中的单个单元格呈现。与单元格数组等效的Python是一个列表。因此,如果您真的想在Python中创建num2cell等效项,则可以创建一个与Python NumPy数组具有相同维度的列表,并确保此列表中的每个元素都位于正确的位置。像这样的东西会起作用:

import numpy as np

def num2cell(a):
    if type(a) is np.ndarray:
        return [num2cell(x) for x in a]
    else:
        return a         

递归遍历NumPy数组的每个维度。对于此数组中维度中的每个元素,如果该元素也是一个数组,则对于下一维度中的每个元素,转换为列表表示形式。基本情况是当我们实际达到实际数字时,如果是这种情况,只需返回实际数字。

这是在我的Python工作区中定义num2cell之后的一个工作示例:

In [26]: import numpy as np

In [27]: A = np.random.rand(4,3,3)

In [28]: B = num2cell(A)

In [29]: A[0]
Out[29]:
array([[ 0.52971132,  0.91969837,  0.77649566],
       [ 0.51080951,  0.8086879 ,  0.61840573],
       [ 0.7291165 ,  0.0492292 ,  0.53997368]])

In [30]: B[0]
Out[30]:
[[0.52971132352406691, 0.91969837282865874, 0.77649565991300817],
 [0.51080951338602765, 0.80868789862631529, 0.61840573261134801],
 [0.72911649507775378, 0.049229201932639577, 0.53997367763478676]]

In [31]: A[1][1]
Out[31]: array([ 0.41724412,  0.94679946,  0.79899245])

In [32]: B[1][1]
Out[32]: [0.41724411973558406, 0.9467994633124529, 0.7989924496851234]

我们在这里可以看到B是NumPy数组A的列表表示。

答案 2 :(得分:1)

取决于其余代码的功能。一般来说,Matlab使用单元格来表示数组数组,其中内部数组可以具有不同的大小和形状。

要回答你的问题,我认为你所做的基本上就是你想要做的,即创建一个阵列数组。

答案 3 :(得分:1)

.astype(np.object_)很可能是你需要的东西。考虑一下这个matlab代码:

x = [1 2 3 4]
y = num2cell(x)
y(end) = 'hello'

在numpy中,转换为:

x = np.array([1, 2, 3, 4])
y = x.astype(np.object_)
y[-1] = 'hello'

答案 4 :(得分:-2)

一个完全不同的路线是使用matlabs python接口,它允许你调用matlab引擎,从而也可以调用python中的matlab代码。见https://se.mathworks.com/help/matlab/matlab-engine-for-python.html