2011-11-08 16 views
13

Tengo un vector y de longitud n. y (i) es un número entero en 1..m. ¿Hay una manera más sencilla de convertir y en una matriz lógica ny m yy, donde yy (i, j) = 1 si y (i) = j, pero 0 en caso contrario? Así es como he estado haciendo:¿Convertir vector en matriz lógica?

% If m is known (m = 3 here), you could write it out all at once 
yy = [y == 1; y== 2; y == 3]; 
yy = reshape(yy, n, 3); 

o

% if m is not known ahead of time 
yy = [ y == 1 ]; 
for i = 2:m; 
    yy = [ yy; y == i ]; 
end 
yy = reshape(yy, n, m); 
+0

He encontrado otra manera ... no estoy seguro de si esto es mejor ... pero al menos cabe en una línea: yy = repmat (y, 1, m) == repmat (1: m, n, 1); – notrick

+1

'bsxfun' es una de las funciones multiproceso de Matlab. Por lo tanto, es probable que sea más rápido que sus soluciones. – Jonas

Respuesta

9

Puede utilizar bsxfun para este

yy = bsxfun(@eq,y(:),[1,2,3]) 

y se transforma (si es necesario) a un vector columna, mientras que el otro vector es un vector de fila. bsxfun expande implícitamente las matrices m-por-1 y 1-por-n de modo que el resultado se convierte en m-by-n.

5

Si n * m es lo suficientemente grande (ym es, por sí mismo, suficientemente grande), es una buena idea crear yy como una matriz dispersa. Su vector y es realmente un tipo especial de formato de matriz dispersa, pero podemos traducirlo al formato integrado de matriz dispersa haciendo lo siguiente.

yy = sparse(1:length(y), y, 1); 

Esto mantendrá su almacenamiento en O (n). No va a estar haciendo muchos favores si está usando yy para una gran cantidad de indexación. Si ese es el caso, es mejor que utilice su estructura dispersa original (es decir, y).

+0

+1 Definitivamente una mejor alternativa al uso de 'bsxfun'. –

1

Una ligera modificación en el método:

% A n-dimensional vector y, with values in some range 1..m 
m = 4; 
n = 7; 
y = randi([1 m], n, 1); 

% Preallocating a n by m matrix of zeros 
nXm = zeros(n, m); 

% In each pass of this loop a single column of nXm is updated, where 
% for each column index j in nXm, if y(i) = j then nXm(i,j) = 1 
for j = 1:m; 
    nXm(:,j) = (y == j); 
end 
1

De aprendizaje automático en Coursera:

yy = eye(m)(y, :) 

Esto requiere que la lista sea una gama 1:m (como se indica OP). Para obtener una lista irregulares, como [2 3 5], hacer esto

yy = eye(m)(:, [2 3 5])(y, :) 

Nota: no probados en MATLAB.

+0

(Pero aún preferiría el camino de @Jonas, muy limpio). –