如何在Python 3中翻译MATLAB单元?
只是给你一些背景: 我必须将一些MATLAB代码翻译成Python3One,但在这里我遇到了一个小问题 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
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的代码进行分解并提供反馈:
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中更自然/原生。