MATLAB中的ind2sub相当于Python

时间:2015-03-11 19:00:44

标签: python matlab numpy

Matlab有两个函数用于将矩阵下标转换为线性索引,反之亦然。 (ind2sub和sub2ind)

我找到了R的等价物,但在Python中有相同的方法吗?

4 个答案:

答案 0 :(得分:20)

Google搜索引导我访问此链接:https://github.com/jjakeman/pyheat/blob/master/utilities/math_utils.py

据我所知,MATLAB中没有直接实现这些函数


事实证明我无法正确阅读文档。如果您想要sub2ind的功能,则需要ravel_multi_index功能。函数声明表明您需要两个输入。第一个输入是2D numpy数组,其中每一行都是特定维度的位置。例如,如果要在2D矩阵上应用ind2sub,则应指定2D numpy数组,其中第一行包含所需的所有行位置,第二行包含所有行位置您想要的列位置。第二个输入是确定每个维度大小的元组,因此对于2D数组,它是行数和列数。

要执行ind2sub,您需要unravel_index功能。第一个输入是一个线性索引数组,您希望将其转换为数组中每个维度的位置。第二个输入是像以前一样的维度元组。

如果您想尝试自己实施这些内容,我将把帖子留在底层,以备后人使用。


但是,你当然可以自己实现这些。我假设是因为您使用numpy标记了帖子,您需要numpy - esque解决方案。请记住,在numpy中您可以访问主要元素,而不是主要元素,因此给定两个数组,其中一个用于行,另一个用于列索引(0索引),2D矩阵的sub2ind非常简单:

def sub2ind(array_shape, rows, cols):
    return rows*array_shape[1] + cols

array_shape是一个包含两个元素的数组,其中第一个元素是矩阵中的行数,第二个元素是列数。如果您还记得,可以通过以下方式访问行主矩阵中的元素:

ind = r*cols + c

(r,c)是您想要的行和列索引,只要它是0索引的。换句话说,你会使用整数除法和模数:

def ind2sub(array_shape, ind):
    rows = (ind.astype('int') / array_shape[1])
    cols = (ind.astype('int') % array_shape[1]) # or numpy.mod(ind.astype('int'), array_shape[1])
    return (rows, cols)

这里,输出是一个双元素元组,其中第一个元素是行位置,第二个元素是列位置。要总结ind2sub,要访问所需的行,请使用线性索引并对列进行整数除法。要获得所需的列,可以找到模数或余数。进入3个维度以及之后会有点复杂。我将让您看一下上面提到的链接,了解更多详情。

显然,我没有在上述功能中进行任何错误检查,所以在这种情况下你显然会使用array_shape。做你想做的更好的方法是:

def sub2ind(array_shape, rows, cols):
    ind = rows*array_shape[1] + cols
    ind[ind < 0] = -1
    ind[ind >= array_shape[0]*array_shape[1]] = -1
    return ind

def ind2sub(array_shape, ind):
    ind[ind < 0] = -1
    ind[ind >= array_shape[0]*array_shape[1]] = -1
    rows = (ind.astype('int') / array_shape[1])
    cols = ind % array_shape[1]
    return (rows, cols)

我做了一些基本的错误检查,以确保sub2ind的行或列或ind2sub的线性索引没有超出范围。我将这些位置设置为-1,这样你就知道你搞砸了某个地方。

祝你好运!

答案 1 :(得分:8)

我认为你想要ravel_multi_indexunravel_index

答案 2 :(得分:3)

在@rayryeng和@ theblackcat的答案的基础上,你还应该注意到你将不得不使用Fortran样式索引,并且回想起Python被索引为0而MATLAB是1索引。

Fortran风格的要求让我感到有些困惑。

在Python中:

np.unravel_index(7, [1, 2, 3, 4], 'F')
(0, 1, 0, 1)

并在MATLAB / Octave中

[a, b, c, d] = ind2sub([1, 2, 3, 4], 8)
a =  1
b =  2
c =  1
d =  2

答案 3 :(得分:0)

对于2D矩阵,可以使用Python内置的proc = subprocess.Popen(["ip -o -6 addr list | awk '{{print $4}}' | cut -d/ -f1"], stdout=subprocess.PIPE, shell=True) ipv6_all = proc.communicate()[0] 函数(返回除数的商和余数)。要获取divmod矩阵的下标(r,c),请使用:

nrows x ncols用于行优先排序

(r, c) = divmod(ind, ncols)用于列的主要排序


例如,按行优先(C风格)的3x6矩阵:

(c, r) = divmod(ind, nrows)

  0     1     2     3     4     5
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)

  6     7     8     9    10    11
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)

 12    13    14    15    16    17
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)

3x6矩阵,按列优先(Fortran样式)排序:

(0, 0) = divmod(0, 6)
(0, 3) = divmod(3, 6)
(1, 0) = divmod(6, 6)
(1, 5) = divmod(11, 6)
(2, 2) = divmod(14, 6)

  0     3     6     9    12    15
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)

  1     4     7    10    13    16
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)

  2     5     8    11    14    17
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)