Logical Indexing for a slice of a 3D-Matrix

8 views (last 30 days)
Lemar DeSalis
Lemar DeSalis on 16 May 2011
Commented: Jan Siegmund on 22 May 2020
I have two matrices, on which I do some work:
% MyMat1: n x m x 1
% MyMat2: n x m x 3
This is what I do until now:
ValsToBeProcessed = (MyMat1 > 5);
MyMat2_1 = MyMat2(:,:,1);
MyMat2_2 = MyMat2(:,:,2);
MyMat2_3 = MyMat2(:,:,3);
MyMat2_2(ValsToBeProcessed) = MyMat1(ValsToBeProcessed);
MyMat2 = cat(3, MyMat2_1, MyMat2_2, MyMat2_3);
Is there any simpler way to do this? Something like:
ValsToBeProcessed = (MyMat1 > 5);
MyMat2(ValsToBeProcessed, 2) = MyMat1(ValsToBeProcessed);

Answers (6)

Lemar DeSalis
Lemar DeSalis on 16 May 2011
Thanks for all your answers!
In the meantime I found a different solution:
ValsToBeProcessed3D = false(size(MyMat2));
ValsToBeProcessed3D(:,:,2) = ValsToBeProcessed;
MyMat2(ValsToBeProcessed3D) = MyMat1(ValsToBeProcessed);
This is more "readable" to me, so I'll use that version (although your methods may be faster).
  2 Comments
Sean de Wolski
Sean de Wolski on 16 May 2011
That's actually a winner in timings :) Congrats!
+1
Teja Muppirala
Teja Muppirala on 16 May 2011
Nice work. Easy to read, and efficient

Sign in to comment.


Sean de Wolski
Sean de Wolski on 16 May 2011
idx = find(MyMat1>5); %indices in 2d matrix
MyMat2(idx+numel(MyMat1)) = MyMat1(idx);
%indices in 3d matrix and extracted from 2d matrix
NOTE:
%I can't guarantee that this will be any faster than your original way compacted to:
slice2 = MyMat2(:,:,2)
idx = MyMat1>5;
slice2(idx) = MyMat1(idx);
MyMat2(:,:,2) = slice2;

Andrei Bobrov
Andrei Bobrov on 16 May 2011
bsxfun(@times,MyMat2,(MyMat1>5));
EDIT
M5 = MyMat1>5;
MyMat2(find(M5)+numel(MyMat2)/3)=MyMat1(M5);
  2 Comments
Sean de Wolski
Sean de Wolski on 16 May 2011
They only want the second slice, not all three. And you'd have to convert the logical expression to the class of MyMat for the multiplication op to work.
cast(MyMat1>5,class(MyMat2))
Andrei Bobrov
Andrei Bobrov on 16 May 2011
Hi Sean de! Excuse me, my carelessness, correct...

Sign in to comment.


Teja Muppirala
Teja Muppirala on 16 May 2011
Probably a bit faster:
IDX = cast(MyMat1>5,class(MyMat1));
MyMat2(:,:,2) = MyMat1.*IDX+MyMat2(:,:,2).*(1-IDX);

Sean de Wolski
Sean de Wolski on 16 May 2011
Obligatory timings :)
MyMat2store = rand(1000,1000,3);
MyMat1 = rand(1000)*10;
t1 = 0;
t2 = 0;
t3 = 0;
for ii = 1:30;
MyMat2 = MyMat2store;
tic
idx = find(MyMat1>5);
MyMat2(idx+numel(MyMat1)) = MyMat1(idx);
t1 = t1+toc;
MyMat2 = MyMat2store;
tic
slice2 = MyMat2(:,:,2);
idx = MyMat1>5;
slice2(idx) = MyMat1(idx);
MyMat2(:,:,2) = slice2;
t2 = t2+toc;
MyMat2 = MyMat2store;
tic
IDX = cast(MyMat1>5,class(MyMat1));
MyMat2(:,:,2) = MyMat1.*IDX+MyMat2(:,:,2).*(1-IDX);
t3 = t3+toc;
end
disp([t1 t2 t3]);
%with MyMat1 = rand(1000)*10
% 2.9776 2.8133 2.6096
% 2.9078 2.772 2.5669
%with MyMat1 = rand(1000)*7
% 2.4349 2.5948 2.6454
% 2.4591 2.6174 2.724
%with MyMat1 = rand(1000)*20
% 3.5691 3.0149 2.6538
% 3.5123 2.9869 2.6282
%with MyMat1 = rand(1000)*5.5
% 1.7049 2.1195 2.6007
% 1.7177 2.1276 2.604
So Teja's method is relatively constant regardless of the percentage of MyMat1 >5. The two extraction methods that I proposed are faster when the percentage of MyMat1>5 is small and slower when that percentage is large. These findings make sense considering the operations involved.

Teja Muppirala
Teja Muppirala on 16 May 2011
After just trying it out of curiousity, I find that a simple FOR loop actually works better than all of these vectorized solutions (though again it depends a little on the composition of MyMat1) The JIT has really become incredibly good over the last couple of years.
N = numel(MyMat1);
for n = 1:N
if MyMat1(n) > 5
MyMat2(N+n) = MyMat1(n);
end
end
  1 Comment
Jan Siegmund
Jan Siegmund on 22 May 2020
Loops work wonderful on double. Try using a self written numeric classes and loops are devastatingly slow.

Sign in to comment.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!