Grouping values in a matrix according to a value in a row & its index position

24 views (last 30 days)
Hello, say I have the following matrix:
51 71 0
48.87 63.38 -2.30769230769231
42.15 55.97 -2.30769230769231
40.22 47.47 -2.30769230769231
39.84 38.75 -1.92307692307692
40.577 34.19 -1.15384615384615
50 30 0
And I wanted to group different rows together according to equal values of the 3rd column, but index position matters, so if I have two equal values in a 3rd column but they are not next to each other in their index position, do not group together.
Which would give me:
51 71 0
48.87 63.38 -2.30769230769231
42.15 55.97 -2.30769230769231
40.22 47.47 -2.30769230769231
39.84 38.75 -1.92307692307692
40.577 34.19 -1.15384615384615
50 30 0
Would I be using the unique function? Thanks

Accepted Answer

Dyuman Joshi
Dyuman Joshi on 16 Mar 2023
Edited: Dyuman Joshi on 16 Mar 2023
Vectorized approach
mat=[51 71 0
48.87 63.38 -2.30769230769231
42.15 55.97 -2.30769230769231
40.22 47.47 -2.30769230769231
39.84 38.75 -1.92307692307692
40.577 34.19 -1.15384615384615
50 30 0];
vec=(1:size(mat,1))';
%Indices of rows in 3rd column which are not equal to the next row
%Using tolerance instead of comparing to zero
idx=vec([abs(diff(mat(:,3)))>1e-4;true])
idx = 5×1
1 4 5 6 7
%Corresponding number of rows in each group
elem=diff([0;idx])
elem = 5×1
1 3 1 1 1
%Output
out=mat2cell(mat,elem)
out = 5×1 cell array
{[ 51 71 0]} {3×3 double } {[39.8400 38.7500 -1.9231]} {[40.5770 34.1900 -1.1538]} {[ 50 30 0]}
"what if I wanted each group to be stored in a different matrix and each value is in its corresponding column"
Any particular reason why you want to do that?
You can do that, but it is not recommended, as it inefficient and difficult to work with. Read - Why Variables should not be named Dynamically
  2 Comments
JIAN-HONG YE ZHU
JIAN-HONG YE ZHU on 16 Mar 2023
I wanted to put it in different matrices cause I need to do some operations between matrices, cause all of these points are different points in a A* path planning function. So between group 1 and group 2 I would like to find for example the distance between these two points. And x and y are column 1 and column 2 respectively. So I find the hypotenuse between these points.
The reason for grouping is because if column 3 does not change (which is the angle), I know the points are from a same group. So to find the distance between group 2 and group 3. I would calculate the hypotenuse between 48.8700 63.3800 & 39.8400 38.7500.
Dyuman Joshi
Dyuman Joshi on 19 Mar 2023
You can do that from via the cell array as well.
mat=[51 71 0
48.87 63.38 -2.30769230769231
42.15 55.97 -2.30769230769231
40.22 47.47 -2.30769230769231
39.84 38.75 -1.92307692307692
40.577 34.19 -1.15384615384615
50 30 0];
vec=(1:size(mat,1))';
idx=vec([abs(diff(mat(:,3)))>1e-4;true]);
elem=diff([0;idx]);
%storing only 1st 2 columns
out=mat2cell(mat(:,1:2),elem);
out{2}(1,:)
ans = 1×2
48.8700 63.3800
out{3}
ans = 1×2
39.8400 38.7500
norm(out{2}(1,:)-out{3})
ans = 26.2331

Sign in to comment.

More Answers (1)

Amit Dhakite
Amit Dhakite on 16 Mar 2023
Edited: Amit Dhakite on 16 Mar 2023
Hi Jian-Hong,
As per my understanding, you want to group different rows based on the equal values of the 3rd column, only if these rows are next to each other.
The unique() function can indeed be used to group rows based on equal values in a specific column. However, it does not take into account the index position of the rows, and therefore it would not meet your requirement of only grouping together rows with equal values in the 3rd column if they are next to each other in their index position.
To achieve this, you can manually loop through the matrix and group the rows. The approach is to initialize an empty cell array to store the groups of rows. Then, you loop through the sorted matrix and group the rows with equal 3rd column values together. Finally, you display the groups of rows. It can be done as follows:
% Example matrix
A = [51 71 0; 48.87 63.38 -2.30769230769231; 42.15 55.97 -2.30769230769231; 40.22 47.47 -2.30769230769231; 39.84 38.75 -1.92307692307692; 40.577 34.19 -1.15384615384615; 50 30 0];
% Initialize cell array for storing groups of rows
groups = {};
% Loop through sorted matrix and group rows with equal 3rd column values together
currentGroup = [];
currentValue = A(1,3);
for i = 1:size(A,1)
if A(i,3) == currentValue
currentGroup = [currentGroup; A(i,:)];
else
groups = [groups; {currentGroup}];
currentGroup = A(i,:);
currentValue = A(i,3);
end
% if its the last row, then just add this currentGroup to the groups
% array
if i == size(A,1)
groups = [groups; {currentGroup}];
end
end
% Display the groups of rows
for i = 1:numel(groups)
disp(['Group ', num2str(i), ':']);
disp(groups{i});
end
Group 1:
51 71 0
Group 2:
48.8700 63.3800 -2.3077 42.1500 55.9700 -2.3077 40.2200 47.4700 -2.3077
Group 3:
39.8400 38.7500 -1.9231
Group 4:
40.5770 34.1900 -1.1538
Group 5:
50 30 0
To know more about the functions used above, kindly refer to the following links:
  1. size(): https://www.mathworks.com/help/matlab/ref/size.html
  2. numel(): https://www.mathworks.com/help/matlab/ref/double.numel.html
  3. num2str(): https://www.mathworks.com/help/matlab/ref/num2str.html
  1 Comment
JIAN-HONG YE ZHU
JIAN-HONG YE ZHU on 16 Mar 2023
Hello, thanks a lot for your explanation. I see the the groups are stored in a 5x1 cell, what if I wanted each group to be stored in a different matrix and each value is in its corresponding column?

Sign in to comment.

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!