2013-03-05 122 views
13

Matlab提供了函數sub2ind,它「返回行和列下標的線性索引等價物......矩陣......」。如何獲得一個numpy數組的線性索引(sub2ind)

我需要這個sub2ind函數或類似的東西,但我沒有找到任何類似的Python或Numpy函數。我怎樣才能獲得這個功能?

這是從matlab documentation(同上頁)爲例:

Example 1 

This example converts the subscripts (2, 1, 2) for three-dimensional array A 
to a single linear index. Start by creating a 3-by-4-by-2 array A: 

rng(0,'twister'); % Initialize random number generator. 
A = rand(3, 4, 2) 

A(:,:,1) = 
    0.8147 0.9134 0.2785 0.9649 
    0.9058 0.6324 0.5469 0.1576 
    0.1270 0.0975 0.9575 0.9706 
A(:,:,2) = 
    0.9572 0.1419 0.7922 0.0357 
    0.4854 0.4218 0.9595 0.8491 
    0.8003 0.9157 0.6557 0.9340 

Find the linear index corresponding to (2, 1, 2): 

linearInd = sub2ind(size(A), 2, 1, 2) 
linearInd = 
    14 
Make sure that these agree: 

A(2, 1, 2)   A(14) 
ans =     and = 
    0.4854    0.4854 

回答

20

我想你想使用np.ravel_multi_index。隨着numpy的一個從零開始的索引,並考慮到MATLAB數組是Fortran語言風格,相當於您的MATLAB例子是:

>>> np.ravel_multi_index((1, 0, 1), dims=(3, 4, 2), order='F') 
13 

只要你明白是怎麼回事,你可以得到相同的結果與你的指數的點積和陣列的步幅:

>>> a = np.random.rand(3, 4, 2) 
>>> np.dot((1, 0, 1), a.strides)/a.itemsize 
9.0 
>>> np.ravel_multi_index((1, 0, 1), dims=(3, 4, 2), order='C') 
9 
>>> a[1, 0, 1] 
0.26735433071594039 
>>> a.ravel()[9] 
0.26735433071594039 
+3

這是有點誤導。這使得它看起來像你需要知道數組的內存佈局以使用不正確的平面索引。 strides方法只適用於C-Contiguous數組,但這總是正確的:'A [idx] == A.flat [flat_idx] == A.ravel()[flat_idx]'if flat_idx = np.ravel_multi_index (idx,A.shape)'。儘管'flat_idx'在matlab和numpy中的計算方式不同,這很好。 – 2013-03-05 23:01:34

1

這是我如何解決了這個問題對我來說,重寫以類似於上面給出的例子。

主要想法是使用arangereshape創建索引的幫助程序陣列。

In [1]: import numpy as np 

In [2]: A = np.random.rand(3,4,2) 

In [3]: A 
Out[3]: 
array([[[ 0.79341698, 0.55131024], 
     [ 0.29294586, 0.22209375], 
     [ 0.11514749, 0.15150307], 
     [ 0.71399288, 0.11229617]], 

     [[ 0.74384776, 0.96777714], 
     [ 0.1122338 , 0.23915265], 
     [ 0.28324322, 0.7536933 ], 
     [ 0.29788946, 0.54770654]], 

     [[ 0.13496253, 0.24959013], 
     [ 0.36350264, 0.00438861], 
     [ 0.77178808, 0.66411135], 
     [ 0.26756112, 0.54042292]]]) 

In [4]: helper = np.arange(3*4*2) 

In [5]: helper 
Out[5]: 
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
     17, 18, 19, 20, 21, 22, 23]) 

In [6]: helper = helper.reshape([3,4,2]) 

In [7]: helper 
Out[7]: 
array([[[ 0, 1], 
     [ 2, 3], 
     [ 4, 5], 
     [ 6, 7]], 

     [[ 8, 9], 
     [10, 11], 
     [12, 13], 
     [14, 15]], 

     [[16, 17], 
     [18, 19], 
     [20, 21], 
     [22, 23]]]) 

In [8]: linear_index = helper[1,0,1] 

In [9]: linear_index 
Out[9]: 9 

需要注意的是:

  • 行和列在numpy的關於Matlab的切換。
  • Matlab的從1開始,Python和NumPy的指標爲0