Reputation: 1193
Suppose I have D, an X-by-Y-by-Z data matrix. I also have M, an X-by-Y "masking" matrix. My goal is to set the elements (Xi,Yi,:) in D to NaN when (Xi,Yi) in M is false.
Is there any way to avoid doing this in a loop? I tried using ind2sub
, but that fails:
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
I suspect I'm missing something obvious here. (:
Upvotes: 13
Views: 3566
Reputation: 36710
Reshape is basically for free, you can use it here for an efficient solution. reducing the whole to a 2d problem.
sz=size(D);
D=reshape(D,[],sz(3)); %reshape to 2d
D(isnan(M(:)),:)=nan; %perform the operation on the 2d matrix
D=reshape(D,sz); %reshape back to 3d
Upvotes: 0
Reputation: 125854
You can do this by replicating your logical mask M
across the third dimension using REPMAT so that it is the same size as D
. Then, index away:
D_masked = D;
D_masked(repmat(~M,[1 1 size(D,3)])) = NaN;
If replicating the mask matrix is undesirable, there is another alternative. You can first find a set of linear indices for where M
equals 0, then replicate that set size(D,3)
times, then shift each set of indices by a multiple of numel(M)
so it indexes a different part of D
in the third dimension. I'll illustrate this here using BSXFUN:
D_masked = D;
index = bsxfun(@plus,find(~M),(0:(size(D,3)-1)).*numel(M));
D_masked(index) = NaN;
Upvotes: 13
Reputation: 4504
My Matlab is a bit rusty but I think logical indexing should work:
D_masked = D;
D_masked[ M ] = NaN;
(which probably can be combined into one statement with a conditional expression on the rhs...)
Upvotes: -3