2013-03-05 21 views
13

Matlab cung cấp hàm sub2ind "trả về chỉ số tuyến tính tương đương với hàng và cột subscripts ... cho ma trận ...".Cách lấy chỉ số tuyến tính cho một mảng numpy (sub2ind)

Tôi cần chức năng này sub2ind hoặc chức năng tương tự, nhưng tôi không tìm thấy bất kỳ chức năng Python hoặc Numpy tương tự nào. Làm thế nào tôi có thể nhận được chức năng này?

Đây là một ví dụ từ matlab documentation (cùng một trang như trên):

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 

Trả lời

20

Tôi nghĩ rằng bạn muốn sử dụng np.ravel_multi_index. Với số không dựa indexing của NumPy, và có tính đến tài khoản đó mảng matlab là phong cách Fortran, tương đương với ví dụ matlab của bạn là:

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

Chỉ cần để bạn hiểu những gì đang xảy ra, bạn có thể nhận được kết quả tương tự với sản phẩm chấm của các chỉ mục của bạn và các bước tiến của mảng:

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

Đây là một chút gây hiểu lầm. Điều này làm cho nó trông giống như bạn cần phải biết bố trí bộ nhớ của một mảng để sử dụng lập chỉ mục phẳng mà không đúng. Phương thức strides sẽ chỉ hoạt động trên các mảng C-Contiguous, trong khi điều này sẽ luôn đúng: 'A [idx] == A.flat [flat_idx] == A.ravel() [flat_idx]' nếu 'flat_idx = np.ravel_multi_index (idx, A.shape) '. Bạn nên lưu ý rằng mặc dù 'flat_idx' được tính toán khác nhau trong MATLAB và có nhiều. –

1

Đây là cách tôi giải quyết vấn đề đối với tôi, viết lại là giống như ví dụ đưa ra ở trên.

Ý tưởng chính là tạo một mảng trợ giúp với các chỉ mục sử dụng 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 

Lưu ý rằng:

  • hàng và cột được bật trong NumPy liên quan đến Matlab.
  • Matlab bắt đầu chỉ với 1, Python và NumPy với 0.
Các vấn đề liên quan