2014-04-15 19 views
5

sto cercando vectorize la seguente operazione MATLAB:creare una matrice 2D zero riempito con quelli nelle posizioni indicizzate da un vettore

Dato un vettore colonna con indici, voglio una matrice con lo stesso numero di righe della colonna e un numero fisso di colonne. La matrice viene inizializzata con zeri e contiene quelli nelle posizioni specificati dagli indici.

Ecco un esempio dello script che ho già scritto:

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 

Il risultato desiderato è:

yvec = 

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

E 'possibile ottenere lo stesso risultato senza il ciclo for ? Ho provato qualcosa di simile:

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

ma non funziona.

risposta

5

Due approcci che è possibile utilizzare qui.

Approccio 1:

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

Approccio 2 (One-liner):

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

mi piace particolarmente il secondo approccio :) – Muffo

+3

Inoltre sembra 'yvec' ha numero di colonne pari al massimo di' y', così per il secondo approccio è possibile avere una versione generalizzata come 'yvec = bsxfun (@eq, 1: max (y), y)'. – Divakar

+0

Oppure, solo in ottava, '(1: 3) == y', che è l'approccio 2 con [broadcasting] (https://www.gnu.org/software/octave/doc/v4.0.1/Broadcasting.html) . – ederag

4

Ancora un altro approccio:

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

Non conoscevo la rappresentazione sparsa in Matlab ma sembra essere davvero utile in questo caso! – Muffo

+1

Illustrativo, grazie! – KAs

3

Si potrebbe fare questo con accumarray :

yvec = accumarray([(1:numel(y)).' y], 1); 
0

ho fatto in questo modo:

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 
Problemi correlati