2010-08-04 18 views
12

Supongamos que tengo D, una matriz de datos X-por-Y-por-Z. También tengo M, una matriz de "enmascaramiento" X-por-Y. Mi objetivo es establecer los elementos (Xi, Yi, :) en D a NaN cuando (Xi, Yi) en M es falso.¿Cómo puedo indexar una matriz 3-D con una máscara 2-D en MATLAB?

¿Hay alguna manera de evitar hacer esto en un bucle? He intentado utilizar ind2sub, pero que falla:

M = logical(round(rand(3,3))); % mask 
D = randn(3,3,2); % data 

% try getting x,y pairs of elements to be masked 
[x,y] = ind2sub(size(M),find(M == 0)); 
D_masked = D; 
D_masked(x,y,:) = NaN; % does not work! 

% do it the old-fashioned way 
D_masked = D; 
for iX = 1:size(M,1) 
    for iY = 1:size(M,2) 
     if ~M(iX,iY), D_masked(iX,iY,:) = NaN; end 
    end 
end 

Sospecho que me falta algo obvio aquí. (:

Respuesta

12

Usted puede hacer esto mediante la replicación de su máscara lógica M a través de la tercera dimensión usando REPMAT para que sea del mismo tamaño que D Entonces, el índice de distancia:.

D_masked = D; 
D_masked(repmat(~M,[1 1 size(D,3)])) = NaN; 

Si no es deseable replicar la matriz de la máscara, existe otra alternativa. Primero puede encontrar un conjunto de índices lineales donde M es igual a 0, y luego replicar ese conjunto size(D,3) veces, luego cambie cada conjunto de índices por un múltiplo de numel(M) para que indexe una parte diferente de D en la tercera dimensión. Voy a ilustrar esto aquí usando BSXFUN:

D_masked = D; 
index = bsxfun(@plus,find(~M),(0:(size(D,3)-1)).*numel(M)); 
D_masked(index) = NaN; 
+0

ah, por supuesto, eso funciona. para las dimensiones gigantes de D y M, aunque todavía puede ser conveniente no tener que replicarlo ... –

+0

@Matt: Dado que 'M' es una matriz lógica, solo usa 1 byte por elemento, por lo que su replicación no se usará casi tanta memoria como matrices duplicadas de dobles. De hecho, la versión replicada de 'M' usará solo 1/8 de la memoria total que' D' hace. – gnovice

+2

@Matt: para completar, agregué otra solución que evita la replicación de 'M'. Si solo hay unos pocos valores cero en una matriz "M" muy grande, esta nueva solución puede ser más deseable desde el punto de vista del uso de la memoria. – gnovice

-2

Mi Matlab es un poco oxidado, pero creo que la indexación lógica debería funcionar:

D_masked = D; 
D_masked[ M ] = NaN; 

(que probablemente se pueden combinar en una declaración con una expresión condicional en los RHS ...)

+1

ah, yo debería haber incluido que en las "cosas he intentado" :-) si lo hace que sólo enmascarar la primera dimensión Z, de modo D (:,: , 1) tendrá aplicada la máscara pero no D (:,:, 2). ¡gracias por la sugerencia! –

Cuestiones relacionadas