2010-08-04 44 views
12

假设我有一个X-Y-Z-Z数据矩阵D.我也有M,一个X-by-Y“掩蔽”矩阵。我的目标是当M中的(Xi,Yi)为假时,将D中的元素(Xi,Yi,:)设置为NaN。如何在MATLAB中使用2-D蒙版索引3-D矩阵?

有什么办法可以避免在循环中做到这一点?我试着用ind2sub,但失败:

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 

我怀疑我缺少明显的东西在这里。 (:

回答

12

您可以通过在使用REPMAT所以它是大小相同的D第三维复制你的逻辑掩码M这样做,那么,指数走:

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

如果不希望复制掩模矩阵,还有另一种方法。您可以首先找到一组线性索引,其中M等于0,然后复制该集合size(D,3)次,然后将每组索引移动numel(M)的倍数,因此它在第三维中索引D的不同部分。我会用BSXFUN这里说明这一点:

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

啊,当然,这是有效的。对于D和M的巨大尺寸,虽然它可能仍然是可取的而不必复制它... – 2010-08-04 16:45:53

+0

@Matt:由于'M'是一个逻辑矩阵,它只使用每个元素1个字节,所以复制它将不会使用几乎与复制双打矩阵一样多。实际上,复制版本的“M”只会占用D的总内存的1/8。 – gnovice 2010-08-04 16:50:09

+2

@Matt:为了完整起见,我添加了另一个避免复制'M'的解决方案。如果在一个非常大的矩阵“M”中只有几个零值,从内存使用的角度来看,这种新的解决方案可能更为理想。 – gnovice 2010-08-04 17:09:44

-2

我的Matlab是有点生疏,但我认为逻辑索引应该工作:

D_masked = D; 
D_masked[ M ] = NaN; 

(这可能可以用在RHS条件表达式组合成一个语句...)

+1

啊,我应该已经包括在“东西我试过” :-)如果你这样做,你只能掩盖第一Z尺寸,所以d(:,: ,1)将应用掩模但不包括D(:,:,2)。还是)感谢你的建议! – 2010-08-04 16:27:33