Решение Код: Один подход с sort
(для получения индексов по столбцам отсортирован) & затем bsxfun
(чтобы получить линейные упорядоченные индексы) -
%// Get 2D array of column-sorted indices for input X
[~,sorted_idx] = sort(X,1)
%// Get linear indices for the first k rows of sorted indices
lin_idx = bsxfun(@plus,sorted_idx(1:k,:),[0:size(X,2)-1]*size(X,1))
%// Use those indices to set them in X as zeros
X(lin_idx) = 0;
Пример запуска
1) Входы:
X =
61 67 86 54 49 40 13
48 91 28 70 34 98 87
79 7 27 86 71 58 52
16 10 45 60 79 4 3
56 36 49 50 31 48 87
k =
3
2) Отсортированные показатели:
>> [~,sorted_idx] = sort(X,1)
sorted_idx =
2 3 2 1 1 1 1
4 4 3 4 2 4 3
5 5 4 5 5 5 4
1 1 5 2 3 3 2
3 2 1 3 4 2 5
3) Выбрать только первые к индексам из каждой колонки:
>> sorted_idx(1:k,:)
ans =
4 3 3 5 5 4 4
2 4 2 1 2 1 1
5 5 4 4 1 5 3
4) Нам нужно преобразовать эти столбцы индексов для линейных индексов, соответствующих 2D массив, X
. Таким образом, после индексации столбца, используемого в MATLAB, первый столбец остается таким, как он есть, второй столбец должен иметь смещение number of rows in X
, добавленный третий столбец, и добавляется до тех пор, пока не будут покрыты все столбцы.
Выражаясь математически, мы имели бы [0 5 10 15 20 25 30]
, т.е. [0:6]*5
, т.е. положить в общем случае [0:size(X,2)-1]*size(X,1)
, добавляется к sorted_idx(1:k,:)
. Поскольку нам нужно сделать это для каждой строки sorted_idx(1:k,:)
, мы можем использовать автоматическое расширение и суммирование (с @plus
) с bsxfun
. Обратите внимание, что это будет сделано в векторном виде. Таким образом, здесь будет происходить расширение [0:size(X,2)-1]*size(X,1)
, а затем будут выполняться элементарные суммы с sorted_idx(1:k,:)
с использованием @plus
. Таким образом, мы имели бы столь необходимые линейные показатели, как так -
>> lin_idx = bsxfun(@plus,sorted_idx(1:k,:),[0:size(X,2)-1]*size(X,1))
lin_idx =
4 8 13 20 25 29 34
2 9 12 16 22 26 31
5 10 14 19 21 30 33
5) Наконец, мы используем эти индексы, чтобы выборочно устанавливать нули в X
с X(lin_idx) = 0
.
Если у вас есть время, не могли бы вы объяснить, что именно делает bsxfun? Это значительно улучшит этот ответ с помощью такого элегантного решения. – spurra
@BananaCode В него добавлено некоторое объяснение. – Divakar