Компактная нотация, индексация матрицы Матлаб

У меня есть матрица размером n на k, содержащая k чисел в строке. Я хочу использовать эти K чисел в качестве индексов в k-мерную матрицу. Существует ли компактный способ сделать это в MATLAB или я должен использовать цикл for?

Это то, что я хочу сделать (в псевдо-коде MATLAB), но более MATLAB-ish:

for row=1:1:n
    finalTable(row) = kDimensionalMatrix(indexmatrix(row, 1),...
          indexmatrix(row, 2),...,indexmatrix(row, k))
end

3 ответов


если вы хотите избежать использования цикла for, это, вероятно, самый чистый способ сделать это:

indexCell = num2cell(indexmatrix, 1);
linearIndexMatrix = sub2ind(size(kDimensionalMatrix), indexCell{:});
finalTable = kDimensionalMatrix(linearIndexMatrix);

в первой строке каждого столбца indexmatrix в отдельные ячейки массива ячеек с помощью num2cell. Это позволяет нам пройти все k колонок -разделенный запятыми список на sub2ind функция, которая преобразует индексного показатели (строка, столбец и т. д.) в линейные показатели (каждой матрицы элемент пронумерован от 1 до N, N - общее количество элементов в матрице). Последняя строка использует эти линейные индексы для замены цикла for. Хорошее обсуждение индексации матриц (подстрочной, линейной и логической) можно найти здесь.

еще немного пищи для размышлений...

тенденция уклоняться от циклов for в пользу векторизованных решений-это то, к чему привыкли многие пользователи MATLAB (включая меня). Тем не менее, более новые версии MATLAB обрабатывают цикл намного эффективнее. Как обсуждалось в ответ к другому вопросу SO, использование циклов for иногда может привести к более быстрому коду, чем вы получите с векторизованным решением.

Я, конечно, не говорю, что вы больше не должны пытаться векторизовать свой код, только что каждая проблема уникальна. Векторизация будет часто быть более эффективным, но не всегда. Для вашей проблемы, скорость выполнения циклов for против векторизованного кода, вероятно, будет зависеть от того, насколько велики значения n и k есть.


для обработки элементов вектора indexmatrix(row, :) в качестве отдельных индексов вам нужны элементы в виде массива ячеек. Итак, вы можете сделать что-то вроде этого

subsCell = num2cell( indexmatrix( row, : ) );
finalTable( row ) = kDimensionalMatrix( subsCell{:} );

чтобы развернуть subsCell как разделенный запятыми список, к сожалению, вам нужны две отдельные строки. Однако этот код не зависит от k.


преобразуйте свои подиндексы в линейные индексы хакерским способом

ksz = size(kDimensionalMatrix);
cksz = cumprod([ 1 ksz(1:end-1)] );
lidx = ( indexmatrix - 1 ) * cksz' + 1; #'
% lindx is now (n)x1 linear indices into kDimensionalMatrix, one index per row of indexmatrix
% access all n values:
selectedValues = kDimensionalMatrix( lindx );

Ура!