2010-08-04 33 views
12

Giả sử tôi có D, ma trận dữ liệu X-by-Y-by-Z. Tôi cũng có M, một ma trận "mặt nạ" X-by-Y. Mục tiêu của tôi là để thiết lập các yếu tố (Xi, Yi, :) trong D để NaN khi (Xi, Yi) trong M là sai.Làm cách nào để lập chỉ mục ma trận 3-D với mặt nạ 2-D trong MATLAB?

Có cách nào để tránh thực hiện việc này trong vòng lặp không? Tôi đã thử sử dụng ind2sub, nhưng điều đó không thành công:

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 

Tôi nghi ngờ tôi đang thiếu điều gì đó hiển nhiên ở đây. (:

Trả lời

12

bạn có thể làm điều này bằng cách sao chép nạ logic của bạn M qua chiều thứ ba sử dụng REPMAT để nó là kích thước tương tự như D Sau đó, chỉ số đi:.

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

Nếu sao chép ma trận mặt nạ là không mong muốn, có một thay thế khác. Trước tiên, bạn có thể tìm thấy một tập hợp các chỉ số tuyến tính cho vị trí M bằng 0, sau đó nhân bản bộ đó size(D,3) lần, sau đó thay đổi từng bộ chỉ mục theo bội số của numel(M) để chỉ mục một phần khác nhau của D trong thứ nguyên thứ ba. Tôi sẽ minh họa điều này ở đây sử dụng BSXFUN:

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

ah, tất nhiên, nó hoạt động. cho kích thước khổng lồ của D và M mặc dù nó vẫn có thể được mong muốn không phải sao chép nó ... –

+0

@Matt: Vì 'M' là một ma trận logic, nó chỉ sử dụng 1 byte cho mỗi phần tử, vì vậy sao chép nó sẽ không sử dụng lên gần như nhiều bộ nhớ như là ma trận nhân đôi của đôi. Trong thực tế, phiên bản nhân bản của 'M' sẽ chỉ sử dụng 1/8 tổng bộ nhớ mà' D' làm. – gnovice

+2

@Matt: Để hoàn thành, tôi đã thêm một giải pháp khác để tránh sao chép 'M'. Nếu chỉ có một vài giá trị bằng không trong một ma trận rất lớn 'M', thì giải pháp mới này có thể được mong muốn hơn từ quan điểm sử dụng bộ nhớ. – gnovice

-2

Matlab của tôi là một chút gỉ nhưng tôi nghĩ rằng chỉ mục logic nên làm việc:

D_masked = D; 
D_masked[ M ] = NaN; 

(mà có lẽ có thể được kết hợp thành một tuyên bố với một biểu thức điều kiện trên RHS ...)

+1

ah, tôi nên tôi đã bao gồm rằng trong "những điều tôi đã cố gắng" :-) nếu bạn làm điều đó bạn chỉ mặt nạ kích thước Z đầu tiên, vì vậy D (:,: , 1) sẽ có mặt nạ được áp dụng nhưng không có D (:,:, 2). Nhờ đề nghị mặc dù! –

Các vấn đề liên quan