Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python 3中翻译MATLAB单元?_Python_Matlab_Numpy_Scipy - Fatal编程技术网

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

如何在Python 3中翻译MATLAB单元?,python,matlab,numpy,scipy,Python,Matlab,Numpy,Scipy,只是给你一些背景: 我必须将一些MATLAB代码翻译成Python3One,但在这里我遇到了一个小问题 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代码翻译成Python3One,但在这里我遇到了一个小问题

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(...)]]

(确实有太多的值无法粘贴到这里,但我想你已经知道了。)

你需要问的第一个问题是“什么是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语法。尽管附加项只使用一个索引,但我们可以利用这样一个事实,即元组可以在没有括号的情况下声明,并且字典可以使用元组作为索引:

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的代码进行分解并提供反馈:

  • 这与原始Matlab代码(不同的变量名)无关
  • 两个循环都使用
    i
    <代码>j从未定义过
  • [[i][j]
    构建一个包含一个元素的列表
    i
    ,并尝试获取第j个元素。如果
    j
    不是0,这将导致错误
  • list.extend
    a将参数的所有元素单独附加到列表中,在本例中为单独的行<代码>列表。追加是正确的,因为整个3x3矩阵应作为K中的一个元素追加
  • np.zeros(3,3)
    应该是
    np.zeros((3,3))
    (假设
    np
    numpy
    的别名),因为函数的形状是第一个参数,而不是多个参数

  • 使用我在链接文章中演示的Octave/scipy save/loadmat:

    八度音程

    >> 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
    
    >> K{1,2}(1,1)
    ans = 0
    
    >> save -7 kfile.mat K
    
    访问一个单元格中的一个元素:

    >> K{1,2}
    ans =
    
       0   0
       0   0
    
    >> K{1,2}(1,1)
    ans = 0
    
    >> save -7 kfile.mat K
    
    用Python

    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对象数据类型数组;而正则矩阵是二维数值数组。对象数组在许多方面都类似于嵌套的Python列表。

    描述Matlab代码的功能以及您认为难以翻译的原因可能会有所帮助。K矩阵用于表示电气网络的拓扑结构。因此,它将包含长度从1到3最大的其他矩阵。就它得到的结果而言,我可以理解第一个循环(带有K{I,j}),但第二个循环在我看来非常奇怪:K{I,j}(K,K)是什么?我怎么翻译呢?这就是为什么我觉得很难:我只是不明白,所以
    K
    是二维的?那么
    k_拓扑
    k
    之间有什么区别呢?我想最接近的应该是
    dtype=object
    np.array
    。是的,我忘了提到:k_拓扑是我的Python等价于Matlab的k矩阵。好吧,谢谢你的回答,这让我明白了很多事情!所以我想我要检查一个涉及嵌套列表的列表。谢谢。我最终用列表理解来解决我的问题,但我没有使用倍频程,所以我认为你的答案与我的问题无关倍频程与Matlab兼容。我正在说明Matlab结构和numpy结构之间最直接的等价性。但是直接创建2d对象数组有点尴尬,在您的情况下可能不需要。列表在python中更自然/原生。