#matlab #matrix #vector
#matlab — математическая лаборатория #матрица #вектор
Вопрос:
Я не уверен, как сформулировать вопрос, но я думаю, что пример поможет. Предположим, у меня есть вектор y = [3;1;4;1;6]. Я хочу создать матрицу Y =
[0 0 1 0 0 0;
1 0 0 0 0 0;
0 0 0 1 0 0;
1 0 0 0 0 0;
0 0 0 0 0 1]
↑ ↑ ↑ ↑ ↑ ↑
1 2 3 4 5 6
где элемент в каждом столбце равен единице или нулю, соответствующему значению в векторе.
Я обнаружил, что могу сделать это с помощью
Y = []; for k = 1:max(y); Y = [Y (y==k)]; end
Могу ли я сделать это без цикла for (и является ли этот метод более эффективным, если y содержит тысячи элементов)?
Спасибо!
Ответ №1:
Ваш метод неэффективен, потому что вы увеличиваете размер Y
в цикле, что не является хорошей практикой программирования. Вот как можно исправить ваш код:
Ele = numel(y);
Y= zeros(Ele, max(y));
for k = 1:Ele
Y (k,y(k))= 1;
end
И вот альтернативный подход без цикла:
Ele = numel(y); %Finding no. of elements in y
Y= zeros(Ele, max(y)); % Initiailizing the matrix of the required size with all zeros
lin_idx = sub2ind(size(Y), 1:Ele, y.'); % Finding linear indexes
Y(lin_idx)=1 % Storing 1 in those indexes
Комментарии:
1. Спасибо, Сардар_Усама. Отлично работает! Есть ли причина для использования «y.’ » вместо просто «y» в третьей строке. Кроме того, является ли sub2ind более эффективным, чем использование for, если имеется не более 10 столбцов?
2. @Gnubie Потому что размер
I
иJ
вsub2ind(SIZ,I,J)
должен быть одинаковым. Это должно быть эффективно с точки зрения скорости!3. @Sadar_Usama: Я понимаю, почему вы переносили y, но обнаружили, что y’ идентично y.’ (дополнительная точка в вашем ответе). В чем разница?
4. @Gnubie ! Простой
'
— это не транспонирование. Это комплексное сопряжение, которое совпадает с транспонированием, если нет сложного элемента. Прочитайте документацию для справки здесь: mathworks.com/help/matlab/ref/transpose.html и здесь: mathworks.com/help/matlab/ref/ctranspose.html5. @Gnubie Идея использования
sub2ind
на самом деле лучше, чемbsxfun
здесь, особенно еслиy
могут иметь большие значения.
Ответ №2:
Вы можете использовать bsxfun
:
result = double(bsxfun(@eq, y(:), 1:max(y)));
Если вы запускаете код в Matlab версии R2016b или более поздней, вы можете упростить синтаксис до
result = double(y(:)==(1:max(y)));
Другой подход, возможно, более эффективный, заключается в заполнении значений непосредственно с помощью accumarray
:
result = accumarray([(1:numel(y)).' y(:)], 1);
Комментарии:
1. это решение медленное: n ^ 2 операции, из которых n (n-1) являются проверкой, ни к чему не приводящей, и только n приводят к записи 1.
2. @titus Вы правы. Я добавил другой подход, который, вероятно, более эффективен
Ответ №3:
Я нашел другое решение:
E = eye(max(y));
Y = E(y,:);
Комментарии:
1. Это выглядит довольно аккуратно, но не так быстро, как
sub2ind
подход. Осторожно! Еслиmax(y) >> numel(y)
, это становится, безусловно, самым медленным. Но еслиmax(y) << numel(y)
, это почти так же хорошо, какsub2ind
.
Ответ №4:
Другое решение:
Y = repmat(1:max(y), size(y)) == repmat(y, 1, max(y))