簡體   English   中英

如何在Python 3中翻譯MATLAB單元?

[英]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)) 
  1. 這與原始的Matlab代碼(不同的變量名稱)無關
  2. 兩個循環都使用i j永遠不會定義。
  3. [[i][j]]使用一個元素i構建一個列表,並嘗試獲取第j個元素。 如果j不是0,則會導致錯誤。
  4. list.extend a將參數的所有元素分別附加到列表中 - 在這種情況下是單個行。 list.append使用正確,因為整個3x3矩陣應作為K中的一個元素追加。
  5. np.zeros(3, 3)應該是np.zeros((3, 3)) (假設npnumpy的別名)因為函數的形狀是第一個參數,而不是多個參數。

使用我在鏈接帖子中演示的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM