Линейная индексация, логическая индексация и все такое
Мы привыкли к различным формам индексации в 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
) выходного массива определяется как функция формы индексных переменных. Хороший пост об этом - " Сущность индексации " Лорен Шуре.
Следующее описание сфокусировано на индексации числовых массивов, но оно может быть применено к массивам ячеек с индексацией в скобках или фигурными скобками, с очевидным изменением типа вывода (массив ячеек или список через запятую, соответственно). Это будет кратко обсуждено в конце.
Типы индексации в числовых массивах
Индексация может быть классифицирована с учетом следующих двух атрибутов.
В зависимости от количества измерений, к которым относится каждая индексная переменная, индексирование может быть многомерным или линейным. Но это только два крайних случая. Существует промежуточная ситуация, которую можно назвать частично линейной индексацией:
- Чистая многомерная индексация определяет переменную индекса для каждого измерения массива. Отдельные индексы иногда упоминаются как индексы в документации Matlab (см., Например,
sub2ind
). - Чистая линейная индексация определяет единственную переменную индекса, которая пересекает массив по всем измерениям (это можно рассматривать так, как будто все измерения свернуты в одно). Как мы знаем, обход идет сначала по столбцам, затем по строкам, затем по третьим затемнениям и т. Д. (Так называемый главный порядок столбцов).
- Частично линейная индексация: дан массив с
m+n
размеры,n>=2
можно указатьm
индексные переменные для первогоm
измерения (таким образом, используя многомерное индексирование в этих измерениях) и одну переменную индекса для последнегоn
размеры, который интерпретируется как линейный индекс только для этих размеров (последнийn
размеры рушатся в одно).
- Чистая многомерная индексация определяет переменную индекса для каждого измерения массива. Отдельные индексы иногда упоминаются как индексы в документации Matlab (см., Например,
В соответствии с типом значений индекса каждая переменная индекса может быть целочисленной или логической:
- Целочисленное значение, если переменная индекса содержит положительные целые числа;
- Логично, если переменная индекса содержит логические значения.
Классификационные критерии 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
Многомерный, целочисленный:
>> A([1 2], 2, 2) ans = 10 14
Линейный, целочисленный:
>> A([2 5:7]) ans = 3 5 9 6
Частично линейный, целочисленный:
>> A([1 2], 2:4) ans = 1 6 17 5 7 12
Многомерный, логичный:
>> 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.Линейный, логичный:
>> A([false true false false true true true]) ans = 3 5 9 6
(Обратите внимание, что 11 трейлинг
false
значения были пропущены в векторе индексации.)Частично линейный, логичный:
>> A([true true false], [false true true true false false]) ans = 1 6 17 5 7 12
В многомерном или частично линейном индексировании, в котором имеется более одной индексной переменной, каждая из них может быть независимо целочисленной или логической. Это приводит к различным смешанным типам. Например:
Многомерный, логический / целочисленный:
>> A([true false true], [false true true], 2) ans = 10 15 18 11
Частично линейный, целочисленный / логический:
>> 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
Логическая и линейная индексация не являются исключительными типами индексации. Скорее, это две независимые особенности индексации. "Логический" относится к типу значений индекса, а "линейный" означает, что несколько измерений свернуты и проиндексированы как одно. Обе функции могут происходить одновременно.