如何获取numpy数组的线性索引(sub2ind)

18

Matlab提供了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
2个回答

28
我觉得你希望使用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

6
有点误导人。这使得它看起来好像你需要了解数组的内存布局才能使用平坦索引,但事实并非如此。步幅方法只适用于C连续数组,而这将始终成立:A[idx] == A.flat[flat_idx] == A.ravel()[flat_idx],如果flat_idx = np.ravel_multi_index(idx, A.shape)。不过需要注意的是,flat_idx在Matlab和NumPy中的计算方式有所不同。 - Bi Rico

2
这是我解决问题的方法,重写成与上面给出的示例类似的形式。
主要思路是使用 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开始。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接