Select elements of a matrix based on the values of a logical array

51 views (last 30 days)
I have a 23x4 matrix A and a 23x1 logical array B
A = [
2619834.52 1169193.206 2622778.731 1168042.07
2622778.731 1168042.07 2623330.871 1167853.553
2623330.871 1167853.553 2623895.366 1167330.066
2623895.366 1167330.066 2623752.209 1167450.319
2623895.366 1167330.066 2623752.209 1167450.319
2623900.076 1167326.26 2624169.326 1167219.875
2624169.326 1167219.875 2624253.37 1167198.916
2624253.37 1167198.916 2624535.39 1167048.569
2624253.37 1167198.916 2624535.39 1167048.569
2625504.044 1167095.529 2626025.669 1167318.065
2625552.809 1167096.398 2625957.908 1167292.096
2625592.67 1167098.709 2625720.968 1167147.911
2625637.183 1167100.023 2625720.968 1167147.911
2625720.968 1167147.911 2625749.984 1167166.109
2625739.693 1167164.891 2625957.908 1167292.096
2625749.984 1167166.109 2625880.835 1167248.686
2625880.835 1167248.686 2625990.736 1167298.256
2625552.809 1167096.398 2625957.908 1167292.096
2625880.835 1167248.686 2625990.736 1167298.256
2626025.669 1167318.065 2625957.908 1167292.096
2628613.339 1167794.423 2628793.988 1167686.086
2628793.988 1167686.086 2629072.311 1167703.565
2629072.311 1167703.565 2631163.404 1169347.638];
B = [
0
0
0
1
0
0
0
0
1
0
0
0
0
0
0
0
0
1
1
0
0
0
0];
I need to create a 2-column matrix C, where each row of C is a row of A, but picking up only the elements of both the 1st and 2nd columns of A, when the corrisponding element of B = 0, and taking only the elements of both the 3rd and 4th columns of A, when the corresponding element of B = 1. My current "solution" is...
tic
if B==0
C = A(:,1:2)
else
C = A(:,3:4)
end
toc
% Result
C =
2622778.731 1168042.07
2623330.871 1167853.553
2623895.366 1167330.066
2623752.209 1167450.319
2623752.209 1167450.319
2624169.326 1167219.875
2624253.37 1167198.916
2624535.39 1167048.569
2624535.39 1167048.569
2626025.669 1167318.065
2625957.908 1167292.096
2625720.968 1167147.911
2625720.968 1167147.911
2625749.984 1167166.109
2625957.908 1167292.096
2625880.835 1167248.686
2625990.736 1167298.256
2625957.908 1167292.096
2625990.736 1167298.256
2625957.908 1167292.096
2628793.988 1167686.086
2629072.311 1167703.565
2631163.404 1169347.638
Elapsed time is 0.000728 seconds.
...I would like to avoid the "if", and therefore to use a more compact code, maybe only one line (and not slower than now, obviously). Any idea?

Accepted Answer

Guillaume
Guillaume on 18 Oct 2019
Edited: Guillaume on 18 Oct 2019
First, have you noticed that your code doesn't work at all? It either copy all of columns 3 and 4 of A into C if B is all 1s, and copy all of columns 1 and 2 of A otherwise. Note that B == 0 is a logical vector.
C = zeros(size(A, 1), 2); %preallocate destination
C(B, :) = A(B, [3, 4]); %copy columns 3 and 4 where B is true
C(~B, :) = A(~B, [1, 2]); %copy columns 1 and 2 where B is false
edit: fixed embarassing typo in the code
  2 Comments
Guillaume
Guillaume on 18 Oct 2019
Do'h! Fixed the typo in my answer. It should have been C(B, :) = ... and C(~B, :) = ...
I'll repeat, your code doesn't do what you want. It has nothing to do with the version of matlab or conversion to logical.
if B == 0
is only true if all the elements of B are equal to 0. Therefore in your example it is not true and your code simply does:
C = A(:,3:4)
Notice that the 4th row of C is still the 3 and 4th column of the 4th row of A despite B(4) being equal to 1.
That is because you're passing a logical vector (B == 0) to if. When you pass a vector to if, the if branch is only true if all the elements of the vectors are true (and the vector is not empty).
Sim
Sim on 18 Oct 2019
You are right, I did a mistake... and I think I need more coffee to be more awake :)
Thank you very much! Your solution is perfectly working
B = logical(B);
C = zeros(size(A, 1), 2); %preallocate destination
C(B,:) = A(B, [3, 4]); %copy columns 3 and 4 where B is true
C(~B,:) = A(~B, [1, 2]); %copy columns 1 and 2 where B is false

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!