如何在Python 3中翻译MATLAB单元?

时间:2017-02-15 14:56:16

标签: python matlab numpy scipy

只是为了给你一些背景信息:

我必须将一些MATLAB代码翻译成Python 3代码,但在这里我遇到了一个小问题。

Matlab的:

for i in 1:num_nodes
    for j in 1:num_nodes
        K{i,j} = zeros(3,3);

我将其翻译成:

k_topology = [[]]
for i in range(x):
    for i in range(x):
        k_topology[[i][j]].extend(np.zeros(3,3))

此外,在Matlab代码中还有第三个循环:

for k in 1:3
    K{i,j}(k,k) = -1

哪种......也让我心烦意乱?

事实上,我并没有真正看到如何将这种变量转换为Python。另外,我猜我的Python代码有点“破碎” - 而且我并没有真的要求任何人改进它 - 所以我只是问哪个是最好的将Matlab的单元格转换为Python的方法?

根据kazemakase的回答,我终于找到了一些显然简单来翻译它,使用列表理解 - 。实际的Python代码现在看起来像这样:

k_topology = [[np.zeros((3,3)) for j in range(self.get_nb_nodes_from_network())]\
                  for i in range(self.get_nb_nodes_from_network())]

在输出中看起来像这样:

[[array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]]), 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]]), 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])], ..., [array(...)]]

(在这里粘贴它真的太多了,但我认为你得到了它。)

2 个答案:

答案 0 :(得分:3)

您需要问的第一个问题是“一个Matlab单元格,什么可能是一个合适的相应Python类型?”

如果我从我糟糕的旧Matlab时代中正确地记得,一个单元格就是一个容纳混合类型内容的容器。它类似于动态类型的数组或矩阵。它是多维索引的。

Python是动态类型的,因此任何Python contianer都可以基本实现此功能。 Python中的列表被编入索引,因此嵌套列表可以工作 - 但是设置和访问它们有点奇怪:

K = [[None] * num_nodes  for _ in range(num_nodes)]
K[i][j]  # need two indices to access elements of a nested list.

对于特定场景,字典更好地反映了Matlab语法。虽然ditionary只接受一个索引,但我们可以利用这样一个事实,即元组可以不带括号声明,并且字典可以将元组作为索引:

K = {}
for i in range(num_nodes):
    for j in range(num_nodes):
        K[i, j] = np.zeros((3, 3))

        for k in 1:3
            K[i, j][k, k] = -1

虽然字典在语法上更简洁,但元素访问的可能性要低于嵌套列表。嵌套看起来与Matlab代码不同。选择取决于性能或与原始代码的相似性。但是,如果性能是一个问题,那么还有很多事情要考虑,无论如何。总结:没有一种最好的方法。

由于OP明确要求不改进代码,我明确要求他/她忽略这部分答案。

构建对角矩阵的更好方法是使用np.ones而不是在对角线元素上循环。

K = {}
for i in range(num_nodes):
    for j in range(num_nodes):
        K[i, j] = -np.ones((3, 3))

此外,如果这是首选方法,则可以在没有(很多)事先初始化的情况下构建嵌套列表:

K = []
for i in range(num_nodes):
    K.append([])
    for j in range(num_nodes):
        K[-1].append(-np.ones((3, 3)))

现在,为了我的灵魂的平安,让我分开提供关于OP代码的反馈:

k_topology = [[]]
for i in range(x):
    for i in range(x):
        k_topology[[i][j]].extend(np.zeros(3,3))
  1. 这与原始的Matlab代码(不同的变量名称)
  2. 无关
  3. 两个循环都使用i。永远不会定义j
  4. [[i][j]]使用一个元素i构建一个列表,并尝试获取第j个元素。如果j不是0,则会导致错误。
  5. list.extend a将参数的所有元素分别附加到列表中 - 在本例中为单个行。使用list.append是正确的,因为整个3x3矩阵应作为K中的一个元素附加。
  6. np.zeros(3, 3)应为np.zeros((3, 3))(假设npnumpy的别名),因为该函数的形状是第一个参数,而不是多个参数。

答案 1 :(得分:0)

使用我在链接帖子中演示的Octave / scipy save / loadmat:

在Octave会议中

SAPbobsCOM.Company oCompany = new SAPbobsCOM.Company();

访问一个单元格:

>> num_nodes=3
num_nodes =  3
>> num_nodes=3;
>> K=cell(num_nodes, num_nodes);
>> for i = 1:num_nodes
   for j = 1:num_nodes
      K{i,j} = zeros(2,2);
   end
end

>> K
K =
{
  [1,1] =

     0   0
     0   0

  [2,1] =

     0   0
     0   0
etc

访问一个单元格的一个元素:

>> K{1,2}
ans =

   0   0
   0   0

在Python中

>> K{1,2}(1,1)
ans = 0

>> save -7 kfile.mat K

In [31]: from scipy import io In [32]: data = io.loadmat('kfile.mat') In [34]: data Out[34]: {'K': array([[array([[ 0., 0.], [ 0., 0.]]), array([[ 0., 0.], [ 0., 0.]]), array([[ 0., 0.], [ 0., 0.]])], [array([[ 0., 0.], [ 0., 0.]]), array([[ 0., 0.], [ 0., 0.]]), array([[ 0., 0.], [ 0., 0.]])], [array([[ 0., 0.], [ 0., 0.]]), array([[ 0., 0.], [ 0., 0.]]), array([[ 0., 0.], [ 0., 0.]])]], dtype=object), '__globals__': [], '__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.0.0, 2017-02-15 19:05:44 UTC', '__version__': '1.0'} In [35]: data['K'].shape Out[35]: (3, 3) In [36]: data['K'][0,0].shape Out[36]: (2, 2) In [37]: data['K'][0,0][0,0] Out[37]: 0.0 loadmat视为2d对象dtype数组;常规矩阵是2d数字数组。对象数组在很多方面类似于嵌套的Python列表。