[英]How can I translate a MATLAB cell in Python 3?
只是為了給你一些背景:
我必須將一些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(...)]]
(在這里粘貼它真的太多了,但我認為你得到了它。)
您需要問的第一個問題是“什么是 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))
i
。 j
永遠不會定義。 [[i][j]]
使用一個元素i
構建一個列表,並嘗試獲取第j個元素。 如果j
不是0,則會導致錯誤。 list.extend
a將參數的所有元素分別附加到列表中 - 在這種情況下是單個行。 list.append
使用正確,因為整個3x3矩陣應作為K中的一個元素追加。 np.zeros(3, 3)
應該是np.zeros((3, 3))
(假設np
是numpy
的別名)因為函數的形狀是第一個參數,而不是多個參數。 使用我在鏈接帖子中演示的Octave / scipy save / loadmat:
在Octave會話中
>> 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
在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
將一個cell
視為一個二維對象dtype數組; 常規矩陣是2d數字數組。 對象數組在很多方面類似於嵌套的Python列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.