Logical Indexing for a slice of a 3D-Matrix
Mostra commenti meno recenti
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);
Risposte (6)
Lemar DeSalis
il 16 Mag 2011
2 Commenti
Sean de Wolski
il 16 Mag 2011
That's actually a winner in timings :) Congrats!
+1
Teja Muppirala
il 16 Mag 2011
Nice work. Easy to read, and efficient
Sean de Wolski
il 16 Mag 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
il 16 Mag 2011
bsxfun(@times,MyMat2,(MyMat1>5));
EDIT
M5 = MyMat1>5;
MyMat2(find(M5)+numel(MyMat2)/3)=MyMat1(M5);
2 Commenti
Sean de Wolski
il 16 Mag 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
il 16 Mag 2011
Hi Sean de! Excuse me, my carelessness, correct...
Teja Muppirala
il 16 Mag 2011
Probably a bit faster:
IDX = cast(MyMat1>5,class(MyMat1));
MyMat2(:,:,2) = MyMat1.*IDX+MyMat2(:,:,2).*(1-IDX);
Sean de Wolski
il 16 Mag 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
il 16 Mag 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 Commento
Jan Siegmund
il 22 Mag 2020
Loops work wonderful on double. Try using a self written numeric classes and loops are devastatingly slow.
Categorie
Scopri di più su Resizing and Reshaping Matrices in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!