How to find vectors that are multiple of other vectors inside a matrix
Show older comments
For example, given following matrix:
F = [0 1 2; 1 2 3; 0 2 4; 5 6 8; 2 4 6];
0 1 2
1 2 3
0 2 4
5 6 8
2 4 6
Wrong:Identify the rows that are (integer) multiples of some previous rows in the matrix.
In this case 3rd row and 5th row are multiple respectively of 1st and 2nd rows.
- I want to copy the identified rows and create a new matrix out of it.
- Delete the identified rows from the original matrix.
Edit:
Correct: The matrix is composed by integers, each element correspond to a part in weight of a substance so what matters is the proportion, the objective is to delete from the original matrix all the rows that have same proportion of elements. Doesn't matter rows order.
Inside the matrix we could find N rows that are multiple of others, I have to eliminate all of them except one the one that is multiple of 1.
So if I have two rows like this (I made them consecutive to simplify):
2 4 6
1 2 3
I should eliminate one of them, better in this case to delete first row so I can keep the row which is multiplied by one.
Accepted Answer
More Answers (2)
Pawel Jastrzebski
on 25 Apr 2018
Edited: Pawel Jastrzebski
on 25 Apr 2018
I think this will get you going. This code will help you identify which 'NextRow' is a multiplier of 'previousRow':
% DATA
F = [0 1 2; 1 2 3; 0 2 4; 5 6 8; 2 4 6]
% creating a matrix of conditions to be checked
% condition: is next row a multiplier of previous
nR = 2:size(F,1);
pR = 1:size(F,1)-1;
c1 = repelem(nR,pR)';
c2 = [];
for i=1:numel(pR)
ctemp = 1:i;
c2 = [c2 ctemp];
end
% 'c' holds all the cases that needs to be checked
c = [c1 c2'];
% clean the mess
clear c1 c2 ctemp i nR pR;
% 'R' results - true if next row is multiplier of a previous
R = sum(mod(F(c(:,1),:),F(c(:,2),:)),2) == 0;
% store conditions and the result in the table for convenience
t = table(c(:,1),c(:,2), R);
t.Properties.VariableNames= {'nextRow', 'previousRow','IsNextMultiOfPrevious'}
% clean the mess
clear c R;
The outcome:
t =
10×3 table
nextRow previousRow IsNextMultiOfPrevious
_______ ___________ _____________________
2 1 false
3 1 true
3 2 false
4 1 false
4 2 false
4 3 false
5 1 false
5 2 true
5 3 false
5 4 false
6 Comments
It seems that this code does not check to make sure that the row elements are multiplied by the same integer. Unfortunately the example values in the question do not cover this, but my understanding is that the row should be multiplied by one scalar integer. Try it with
1 2 3
3 2 6
Of course this is for the OP to decide, if this is acceptable or not.
Pawel Jastrzebski
on 25 Apr 2018
Thanks for pointing out - I missed this bit.
Andrei Bobrov
on 25 Apr 2018
Nice! But if F:
F = [0 1 2
2 4 6
1 2 3
0 2 4
5 6 8];
Pawel Jastrzebski
on 25 Apr 2018
Edited: Pawel Jastrzebski
on 25 Apr 2018
True. But the multiplier was supposed to be an integer and in your case Row 3 is an instance of Row 2 but the multiplier is 0.5 - at least if you stay true to the requirement that you only look at comparing any given row with the previous ones.
Marco Salvo Cottone
on 25 Apr 2018
Edited: Marco Salvo Cottone
on 25 Apr 2018
Jan
on 25 Apr 2018
The clearing does not have benefits in Matlab, except for some huge arrays, which would exhaust the memory. Usually clearing variables reduces the processing speed only.
Andrei Bobrov
on 25 Apr 2018
Edited: Andrei Bobrov
on 25 Apr 2018
n = size(F,1);
[x,~] = ndgrid(1:n);
l = tril(x,-1);
u = tril(x',-1);
ii = [u(u~=0),l(l~=0)];
R = arrayfun(@(x)rank([F(ii(x,1),:);F(ii(x,2),:)]),1:size(ii,1))' == 1;
out = table(ii,R,'v',{'rows','rank'});
corrected
s = size(F);
F1 = sortrows(F,-(1:s(2)));
[x,~] = ndgrid(1:s(1));
l = tril(x,-1);
u = tril(x',-1);
ii = [u(u~=0),l(l~=0)];
R = arrayfun(@(x)rank([F1(ii(x,1),:);F1(ii(x,2),:)]),1:size(ii,1))' == 1;
F_out = F1(~ismember((1:n)',ii(R,2)),:)
1 Comment
Marco Salvo Cottone
on 25 Apr 2018
Categories
Find more on Logical 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!