MATLAB索引矩阵和数组

示例

MATLAB允许使用几种方法来索引(访问)矩阵和数组的元素:

  • 下标索引-您可以在其中分别指定所需元素在矩阵每个维度中的位置。

  • 线性索引-将矩阵视为向量,无论其尺寸如何。这意味着,您可以用一个数字指定矩阵中的每个位置。

  • 逻辑索引-在其中使用逻辑矩阵(以及true和false值的矩阵)的矩阵,它们的尺寸与尝试索引的矩阵的掩码相同,以指定要返回的值。

现在以下面的3×3矩阵M为例更详细地说明这三种方法:

>> M = magic(3)

ans = 

       8    1    6
       3    5    7
       4    9    2

下标索引

访问元素最直接的方法是指定其行列索引。例如,访问第二行和第三列上的元素:

>> M(2, 3)

ans =

      7

提供的下标数量与尺寸的数量完全匹配M(在此示例中为2)。

请注意,下标的顺序与数学约定相同:行索引是第一个。此外,MATLAB指数开始有1没有0最喜欢的编程语言。

您可以通过传递每个坐标的向量而不是单个数字来一次索引多个元素。例如,要获取整个第二行,我们可以指定我们要第一,第二和第三列:

>> M(2, [1,2,3])

ans =

       3    5    7

在MATLAB中,[1,2,3]可以使用冒号运算符(即)轻松创建矢量1:3。您也可以在索引中使用它。要选择整个行(或列),MATLAB提供了一个快捷方式,只需指定即可:。例如,以下代码还将返回整个第二行

>> M(2, :)

ans =

       3    5    7

MATLAB还提供了一种快捷方式,用于以end关键字的形式指定维的最后一个元素。该end关键字将工作完全一样,如果它是在该维度中的最后一个元素的数量。因此,如果要从列2到最后一列的所有列,可以使用以下代码:

>> M(2, 2:end)

ans =

       5    7

下标索引可能是限制性的,因为它不允许从不同的列和行中提取单个值;它将提取所有行和列的组合。

>> M([2,3], [1,3])
ans =

       3    7
       4    2

例如,下标索引不能仅提取元素M(2,1)或M(3,3)。为此,我们必须考虑线性索引。

线性索引

当您仅使用一维索引时,MATLAB允许您将n维数组视为一维数组。您可以直接访问第一个元素:

>> M(1)

ans = 

       8

请注意,数组在MATLAB中以列优先顺序存储,这意味着您可以通过首先向下浏览列来访问元素。因此M(2),第一列的第二个元素3也M(4)将是第二列的第一个元素,即

>> M(4)

ans = 

        1

存在内置的MATLAB函数标指标转换为线性指标,并反之亦然副:sub2ind和ind2sub分别。您可以手动转换标(r,c所)的线性指标

idx = r + (c-1)*size(M,1)

为了理解这一点,如果我们在第一列中,则线性索引将只是行索引。上面的公式对此适用c == 1,因为(c-1) == 0。在接下来的列中,线性索引是行号加上前几列的所有行。

请注意,end关键字仍然适用,现在指向数组的最后一个元素,即。M(end) == M(end, end) == 2

您还可以使用线性索引来索引多个元素。请注意,如果这样做,则返回的矩阵将具有与索引向量矩阵相同的形状。

M(2:4)返回行向量,因为2:4代表行向量[2,3,4]:

>> M(2:4)

ans =

        3    4    1

作为另一个示例,M([1,2;3,4])由于[1,2;3,4]也是2 x 2矩阵,因此返回2 x 2矩阵。请参见以下代码以说服自己:

>> M([1,2;3,4])

ans =

       8        3
       4        1

请注意,:单独索引时将始终返回列向量:

>> M(:)

ans = 

        8
        3
        4
        1
        5
        9
        6
        7
        2

此示例还说明了使用线性索引时MATLAB返回元素的顺序。

逻辑索引

索引的第三种方法是使用逻辑矩阵,即仅包含true或false值的矩阵作为掩码,以过滤掉不需要的元素。例如,如果我们要查找其中所有M大于5可以使用逻辑矩阵的元素

>> M > 5

ans =

    1    0    1
    0    0    1
    0    1    0

索引M并仅返回大于5以下值的值:

>> M(M > 5)

ans =

        8
        9
        6
        7

如果您希望这些数字保持不变(即保持矩阵的形状),则可以分配给逻辑补语

>> M(~(M > 5)) = NaN

ans = 

    8      NaN    6
    NaN    NaN    7
    NaN    9      Nan

我们可以通过使用逻辑索引来减少包含if和for语句的复杂代码块。

进行非向量化(已通过使用线性索引缩短为单个循环):

for elem = 1:numel(M)
  if M(elem) > 5
    M(elem) = M(elem) - 2;
  end
end

使用逻辑索引可以将其简化为以下代码:

idx = M > 5;
M(idx) = M(idx) - 2;

甚至更短:

M(M > 5) = M(M > 5) - 2;

有关索引的更多信息

高维矩阵

上面提到的所有方法都可以概括为n维。如果我们以三维矩阵M3 = rand(3,3,3)为例,则可以通过以下方式访问三维的第二个切片的所有行和列:

>> M(:,:,2)

您可以使用线性索引访问第二个切片的第一个元素。线性索引只会移动到第一个切片的所有行和所有列之后的第二个切片。因此,该元素的线性索引为

>> M(size(M,1)*size(M,2)+1)

实际上,在MATLAB中,每个矩阵都是n维的:恰好是其他大多数n维的大小都是1。因此,如果a = 2这样a(1) == 2(正如人们所期望的那样),那么也是 a(1, 1) == 2如此a(1, 1, 1) == 2,a(1, 1, 1, ..., 1) == 2等等。这些(尺寸1)“额外”尺寸称为单件尺寸。该命令squeeze将删除它们,并且可以permute用来交换尺寸的顺序(并在需要时引入单件尺寸)。

n维矩阵也可以使用m个下标索引(其中m <= n)。规则是前m-1下标行为正常,而最后一个(m')个下标引用其余(n-m + 1)个维度,就像线性索引引用一个(n-m + 1)个维度一样数组。这是一个例子:

>> M = reshape(1:24,[2,3,4]);
>> M(1,1)
ans =
     1
>> M(1,10)
ans =
    19
>> M(:,:)
ans =
     1     3     5     7     9    11    13    15    17    19    21    23
     2     4     6     8    10    12    14    16    18    20    22    24

元素的返回范围

使用下标索引,如果您在一个以上的维度中指定了多个元素,MATLAB将返回每对可能的坐标。例如,如果你试图M([1,2],[1,3])MATLAB将返回M(1,1)和M(2,3),但它会回M(1,3)和M(2,1)。当您在寻找坐标对列表的元素,但考虑一个较大矩阵的示例时,这似乎是不直观的A = rand(20)(请注意A,现在是20-by- 20),在该矩阵中您想获得右上象限。在这种情况下,不必指定该象限中的每个坐标对(在这种情况下为100成对的坐标),只需指定所需的10行和10列即可A(1:10, 11:end)。切片 像这样的矩阵比需要坐标对列表要普遍得多。

如果确实要获取坐标对列表,则最简单的解决方案是转换为线性索引。考虑以下问题:您有一个要返回的列索引向量,向量的每一行都包含要为矩阵的相应行返回的列号。例如

colIdx = [3;2;1]

因此,在这种情况下,你真的想报复的元素(1,3),(2,2)和(3,1)。因此,使用线性索引:

>> colIdx = [3;2;1];
>> rowIdx = 1:length(colIdx);
>> idx = sub2ind(size(M), rowIdx, colIdx);
>> M(idx)

ans = 

        6    5    4

多次返回一个元素

使用下标和线性索引,您还可以通过重复其索引多次返回元素,因此

>> M([1,1,1,2,2,2])

ans = 

        8    8    8    3    3    3

您可以使用它来复制整个行和列,例如重复第一行和最后一列

>> M([1, 1:end], [1:end, end])

ans = 

        8    1    6    6 
        8    1    6    6
        3    5    7    7
        4    9    2    2


有关更多信息,请参见此处。