2014-04-15 14 views
5

Próbuję wektorować następującą operację MATLAB:Tworzenie zerowej wypełnioną tablicę 2D z nich w pozycjach indeksowanych przez wektor

Biorąc wektor kolumnowy z indeksami, chcę matrycę z same liczba wierszy kolumny i stała liczba kolumn. Macierz jest inicjowana zerami i zawiera te w lokalizacji określone przez indeksy.

Oto przykład skryptu już napisałem:

y = [1; 3; 2; 1; 3]; 
m = size(y, 1); 

% For loop 
yvec = zeros(m, 3); 
for i=1:m 
    yvec(i, y(i)) = 1; 
end 

Pożądany wynik jest:

yvec = 

1  0  0 
0  0  1 
0  1  0 
1  0  0 
0  0  1 

Czy to możliwe, aby osiągnąć ten sam efekt bez pętli for ? Próbowałem coś takiego:

% Vectorization (?) 
yvec2 = zeros(m, 3); 
yvec2(:, y(:)) = 1; 

ale to nie działa.

Odpowiedz

5

Dwa podejścia, których można użyć tutaj.

Podejście 1:

y = [1; 3; 2; 1; 3]; 
yvec = zeros(numel(y),3); 
yvec(sub2ind(size(yvec),1:numel(y),y'))=1 

Podejście 2 (One-liner):

yvec = bsxfun(@eq, 1:3,y) 
+0

Szczególnie podoba mi się drugim podejściu :) – Muffo

+3

również wydaje 'yvec' ma liczbę kolumn równą max' y', więc dla drugie podejście możesz mieć uogólnioną wersję jako 'yvec = bsxfun (@eq, 1: max (y), y)'. – Divakar

+0

Lub, tylko w oktawie, '(1: 3) == y', które jest podejściem 2 z [nadawanie] (https://www.gnu.org/software/octave/doc/v4.0.1/Broadcasting.html) . – ederag

4

Jeszcze inne podejście:

yvec = full(sparse(1:numel(y),y,1)); 
+0

Nie znałem rzadkiej reprezentacji w Matlabie, ale wydaje się to bardzo przydatne w tym przypadku! – Muffo

+1

Zdjęcie, dzięki! – KAs

0

zrobiłem to w ten sposób:

classes_count = 10; 
sample_count = 20; 
y = randi([1 classes_count], 1, sample_count); 

y_onehot = zeros(classes_count, size(y, 2)); 
idx = sub2ind(size(y_onehot), y, [1:size(y, 2)]); 
y_onehot(idx) = 1