Линейная индексация, логическая индексация и все такое

Мы привыкли к различным формам индексации в Matlab:

  • стандарт (используя целые числа вдоль каждого измерения),
  • логический (используя логические значения),
  • линейный (использование одного индекса для обхода массива с более чем одним измерением).

На первый взгляд может показаться, что эти формы являются эксклюзивными: индекс является либо стандартным, либо логическим, либо линейным. Тем не менее, иногда кажется, что существует смесь этих форм. Например,

>> A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2
>> A(A>5)
ans =
     8
     9
     6
     7

Это логическое индексирование, верно? Но у этого также есть некоторые особенности линейного индексирования, потому что вектор столбца возвращается. На самом деле, логический индекс A>5 имеет тот же эффект, что и линейный индекс find(A>5),

В качестве второго примера рассмотрим

>> A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2
>> A(1:2, [true false true])
ans =
     8     6
     3     7

В этом выражении стандартная (целочисленная) индексация используется для первой координаты, а логическая индексация - для второй.

Эти примеры (и более сложные, возникающие на практике) ставят следующие вопросы:

  • Какие виды индексации есть в Matlab?
  • Как они могут быть объединены?
  • Как они должны быть переданы?

1 ответ

Решение

Далее я использую терминологию, которая, по моему мнению, более или менее соответствует стандартной практике Matlab. Однако в некоторых случаях мне приходилось придумывать имя, потому что я не знал о существующем. Пожалуйста, дайте мне знать, если есть больше стандартных имен, чем те, которые я использую.

Этот ответ пытается уточнить различные типы индексации и как они могут быть объединены. Другой вопрос, как форма (size) выходного массива определяется как функция формы индексных переменных. Хороший пост об этом - " Сущность индексации " Лорен Шуре.

Следующее описание сфокусировано на индексации числовых массивов, но оно может быть применено к массивам ячеек с индексацией в скобках или фигурными скобками, с очевидным изменением типа вывода (массив ячеек или список через запятую, соответственно). Это будет кратко обсуждено в конце.

Типы индексации в числовых массивах

Индексация может быть классифицирована с учетом следующих двух атрибутов.

  1. В зависимости от количества измерений, к которым относится каждая индексная переменная, индексирование может быть многомерным или линейным. Но это только два крайних случая. Существует промежуточная ситуация, которую можно назвать частично линейной индексацией:

    • Чистая многомерная индексация определяет переменную индекса для каждого измерения массива. Отдельные индексы иногда упоминаются как индексы в документации Matlab (см., Например, sub2ind).
    • Чистая линейная индексация определяет единственную переменную индекса, которая пересекает массив по всем измерениям (это можно рассматривать так, как будто все измерения свернуты в одно). Как мы знаем, обход идет сначала по столбцам, затем по строкам, затем по третьим затемнениям и т. Д. (Так называемый главный порядок столбцов).
    • Частично линейная индексация: дан массив с m+n размеры, n>=2 можно указать m индексные переменные для первого m измерения (таким образом, используя многомерное индексирование в этих измерениях) и одну переменную индекса для последнего n размеры, который интерпретируется как линейный индекс только для этих размеров (последний n размеры рушатся в одно).
  2. В соответствии с типом значений индекса каждая переменная индекса может быть целочисленной или логической:

    • Целочисленное значение, если переменная индекса содержит положительные целые числа;
    • Логично, если переменная индекса содержит логические значения.

Классификационные критерии 1 и 2 являются независимыми. Категория индекса с точки зрения критерия 1 не имеет отношения к его категории согласно критерию 2. Возможны все комбинации.

Таким образом, согласно приведенной классификации, существует 6 основных типов индексации. Чтобы уточнить, ниже приведен пример для каждого. Все примеры используют массив A = cat(3, magic(3), 9+magic(3)), то есть,

A(:,:,1) =
     8     1     6
     3     5     7
     4     9     2
A(:,:,2) =
    17    10    15
    12    14    16
    13    18    11
  1. Многомерный, целочисленный:

    >> A([1 2], 2, 2)
    ans =
        10
        14
    
  2. Линейный, целочисленный:

    >> A([2 5:7])
    ans =
         3     5     9     6
    
  3. Частично линейный, целочисленный:

    >> A([1 2], 2:4)
    ans =
         1     6    17
         5     7    12
    
  4. Многомерный, логичный:

    >> A([true true false], [false true false], [false true])
    ans =
        10
        14
    

    Интересно, что число логических значений может быть меньше или даже больше, чем размер в измерении, к которому относится индекс:

    >> A([true true], [false true false false], [false true])
    ans =
        10
        14
    

    Недостающие значения интерпретируются как false и прибавочная стоимость должна быть false или произойдет ошибка. Смотрите, например, эту страницу от Mathworks или этот ответ от Jonas.

  5. Линейный, логичный:

    >> A([false true false false true true true])
    ans =
         3     5     9     6
    

    (Обратите внимание, что 11 трейлинг false значения были пропущены в векторе индексации.)

  6. Частично линейный, логичный:

    >> A([true true false], [false true true true false false])
    ans =
         1     6    17
         5     7    12
    

В многомерном или частично линейном индексировании, в котором имеется более одной индексной переменной, каждая из них может быть независимо целочисленной или логической. Это приводит к различным смешанным типам. Например:

  1. Многомерный, логический / целочисленный:

    >> A([true false true], [false true true], 2)
    ans =
        10    15
        18    11
    
  2. Частично линейный, целочисленный / логический:

    >> A([1 2], [true false true false true false])
    ans =
         8     6    10
         3     7    14
    

Если индексируемый массив является разреженной матрицей, все вышеперечисленное все еще применимо, за исключением того, что частично линейная индексация не существует для матриц; и, конечно, результат также невелик.

Индексация клеточных массивов

Все типы индексации, описанные для числовых массивов, могут применяться к массивам ячеек, с одним дополнительным соображением. Массивы ячеек могут быть проиндексированы с помощью скобок или фигурных скобок. В первом случае результатом индексации является массив ячеек. Во втором это разделенный запятыми список содержимого ячейки.

В качестве примера предположим, что числовой массив, использованный в предыдущих примерах, преобразован в массив ячеек. C = num2cell(A), то есть,

C(:,:,1) = 
    [8]    [1]    [6]
    [3]    [5]    [7]
    [4]    [9]    [2]
C(:,:,2) = 
    [17]    [10]    [15]
    [12]    [14]    [16]
    [13]    [18]    [11]

Тогда индексирование, использованное в примере 8 выше, даст массив ячеек

>> C([1 2], [true false true false true false])
ans = 
    [8]    [6]    [10]
    [3]    [7]    [14]

тогда как использование фигурных скобок приведет к получению списка через запятую

>> C{[1 2], [true false true false true false]}
ans =
     8
ans =
     3
ans =
     6
ans =
     7
ans =
    10
ans =
    14 

Сообщение на вынос / TL;DR

Логическая и линейная индексация не являются исключительными типами индексации. Скорее, это две независимые особенности индексации. "Логический" относится к типу значений индекса, а "линейный" означает, что несколько измерений свернуты и проиндексированы как одно. Обе функции могут происходить одновременно.

Другие вопросы по тегам