2013-03-05 1 views
13

Matlab bietet die Funktion sub2ind, die "die linearen Indexäquivalente zu den Zeilen- und Spaltenindizes ... für eine Matrix ... zurückgibt."So erhalten Sie den linearen Index für ein numpiges Array (sub2ind)

Ich brauche diese sub2ind Funktion oder etwas ähnliches, aber ich habe keine ähnliche Python oder Numpy-Funktion gefunden. Wie kann ich diese Funktionalität bekommen?

Dies ist ein Beispiel aus der matlab documentation (gleichen Seite wie oben):

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 

Antwort

20

Ich glaube, Sie np.ravel_multi_index verwenden möchten. Mit der Null-basierten Indizierung von numpy, und unter Berücksichtigung, dass Matlab-Arrays Fortran Stil, das äquivalent zu Ihrem Matlab Beispiel ist:

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

Nur damit Sie verstehen, was los ist, können Sie das gleiche Ergebnis konnten mit das Skalarprodukt Ihrer Indizes und die Schritte des Arrays:

>>> 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

Dies ist ein wenig irreführend. Dies sieht so aus, als ob Sie das Speicherlayout eines Arrays kennen müssen, um eine flache Indizierung zu verwenden, die nicht zutrifft. Die Methode strides funktioniert nur bei C-zusammenhängenden Arrays, wobei dies immer zutrifft: 'A [idx] == A.flat [flat_idx] == A.ravel() [flat_idx]' if 'flat_idx = np.ravel_multi_index (idx, A.form) '. Es ist jedoch gut zu wissen, dass 'flat_idx' in Matlab und Numpy unterschiedlich berechnet werden. –

1

Dies ist, wie ich das Problem für mich gelöst, neu geschrieben oben angegebenes Beispiel ähnlich zu sein.

Die Hauptidee besteht darin, ein Helfer-Array mit den Indizes arange und reshape zu erstellen.

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 

Beachten Sie, dass:

  • Zeilen und Spalten in Numpy in Bezug auf Matlab geschaltet werden.
  • Matlab startet Indizes mit 1, Python und Numpy mit 0.
Verwandte Themen