2016-02-22 15 views
6

Y = zeros(5000,10); y to predefiniowany wektor 5000 x 1 składający się z liczb od 1 do 10;Czy istnieje lepszy sposób zaimplementowania tego kodu MATLAB?

for i= 1:size(Y,1) 
    Y(i,y(i)) = 1; 
end 

Czy istnieje lepszy i prostszy sposób zaimplementować to, ponieważ reszta mojego kodu jest vectorized i nie zawiera żadnych pętli

+2

Kod ten jest prawdopodobnie dość szybko, jak to jest, bo robisz naprawdę niewiele rzeczy w środku. –

Odpowiedz

6

Można użyć bsxfun:

bsxfun(@eq,y,[1:10]) 

Zamiast Twój kod, możesz utworzyć każdy wiersz przy użyciu y(i)==[1:10], który jest ostatecznie zapakowany w bsxfun do wektoryzacji.

Innym pomysłem byłoby obliczanie indeksu:

Y((y-1).*5000+(1:5000).')=1; 
+2

Przyjemny połów @Daniel. Jednak zwrócona macierz wydaje się być logiczna, nawet jeśli uprzednio przydzielono ją zeru() '. Konieczna może być konwersja 'double()'. – Alessiox

+0

A w moim systemie jest to wolniej niż pętla 'for' ... (z konwersją) – zeeMonkeez

+0

dla mnie,' bsxfun() ', włączając konwersję' double() ', zajmuje połowę czasu w odniesieniu do pętla 'for' (0.002190s vs 0.005001s) – Alessiox

2

Można użyć sub2ind:

Y(sub2ind(size(Y), 1:size(Y, 1), y')) = 1; 

to jednak w rzeczywistości może być nieco wolniejszy:

Y = zeros(5000,10); 
y = randi(10, 5000, 1); 

tic 
for jj = 1:1000 
    for i = 1:size(Y,1) 
     Y(i,y(i)) = 1; 
    end 
end 
toc 
% Elapsed time is 0.126774 seconds. 

tic 
for jj = 1:1000 
    Y(sub2ind(size(Y), 1:size(Y, 1), y')) = 1; 
end 
toc 
% Elapsed time is 0.139531 seconds. 

% @Daniel's solution 
tic 
for jj = 1:1000 
    Y = double(bsxfun(@eq, y, 1:10)); 
end 
toc 
%Elapsed time is 0.187331 seconds. 
2

Oto inne podejście: utworzyć macierz sparse przy użyciu y jako indeksów kolumn, a następnie przekonwertować do full razie potrzeby:

Y = full(sparse(1:numel(y), y, 1, numel(y), 10));