2015-11-02 3 views
1

У меня есть огромная матрица MxN матрицу, скажем, A=rand([M,N]); и вектор индекса с N целочисленных значений между 1 и M, скажем, RandomIndex = randi(M,[1,N]);.Доступ к списку записей в MATLAB

Теперь я хотел бы, чтобы сгенерировать вектор-строку с элементами

result = [A(RandomIndex(1),1), A(RandomIndex(2),2), ..., A(RandomIndex(N),N)] 

Что бы быть эффективным способом сделать это? Это должна быть очень дешевая операция, но все мои реализации медленны. Я не думаю, что в Matlab есть обозначение, чтобы сделать это прямо, не так ли?

Самый быстрый вариант до сих пор является

indexFunction = @(r,c) A(r,c); 
result = cell2mat(arrayfun(indexFunction,RandomIndex,1:N,'UniformOutput',false)); 

Есть ли более эффективный способ?

ответ

5

Использование sub2ind

A(sub2ind(size(A), RandomIndex, 1:N)) 

sub2ind преобразует строк и столбцов индексов, данные RandomIndex и 1:N линейных индексов на основе size(A), которые затем можно использовать для индекса A непосредственно.


Другой способ сделать это состоит в использовании RandomIndex и 1:N вернуть NxN матрицу, а затем взять диагональ это с diag

diag(A(RandomIndex, 1:N)).' 

Примечание: .' используется для преобразования строки вектор возвращается diag к вектору столбца.

+2

Плюс 1 для того, чтобы быть первым ** правильным ** ответом на эту проблему. – rayryeng

+0

Оказывается, что репликация sub2ind для этого частного случая выполняется еще быстрее, то есть 'A (M * (0: (N-1)) + RandomIndex)' – Julian

2
M=10;N=50; 
A=rand([M,N]); 
RandomIndex = randi(M,[1,N]); 
out = zeros(1,numel(RandomIndex)); 
for ii = 1:numel(RandomIndex) 
    out(ii)=A(RandomIndex(ii),ii); 
end 
+0

Это не дает правильных значений. Ваш код создает 'A (RandomIndex, 1)'. – IKavanagh

+0

Stupid MATLAB не делает то, что я ожидаю от него ... ну, тогда он вернется в надежный цикл 'for' – Adriaan

+0

Это тоже правильно. Самый канонический способ сделать это. +1. – rayryeng

0

Используйте ваш индекс напрямую.

M = 100;N=100; 
A = rand(M,N); 
% get a random index that can be as large as your matrix 
% 10 rows by 1 column 
idx = randi(numel(A), 10,1); 
t = A(idx); 
+1

Это не дает правильных значений. Ваш код создает 'A (RandomIndex, 1)'. – IKavanagh

+0

@IKavanagh это, безусловно, не создает 'A (RandomIndex, 1)'. Во-первых, нет «RandomIndex», так приятно попробовать. Во-вторых, нет причин, по которым он ограничен «A (, 1)», поскольку он использует случайный индекс всех записей в 'A'. Если бы вы потрудились запустить код, вы увидите, что 'idx (1) = 8148', который является элементом' A (82,48) '. Но эй ... зачем беспокоиться ... просто тролль ... – Matt

+1

Это не дает то, что ищет ОП. Его довольно ясно из его вопроса.У него есть 'A', и у него есть« RandomIndex », если он должен применять« RandomIndex »к' A', как в вашем вопросе типа 't = A (RandomIndex);' он будет генерировать 'A (RandomIndex, 1)' точно так же, как в моем комментарии. Как 'idx (1) = 8148' и' A (82,48) 'каким-либо образом связаны с вопросом? – IKavanagh

1

Другой подход заключается в использовании sparse и логическую индексацию:

M = sparse(RandomIndex, 1:N, 1) == 1; 
out = A(M); 

Первая строка кода создает логическую матрицу, где существует только один true значение, установленное в каждом столбце. Это определяется каждым значением RandomIndex. Мы преобразуем это в матрицу logical, а затем индексируем в вашу матрицу, чтобы получить конечный случайный вектор.

Смежные вопросы