delete rows from matrix if some of its elements equal all elements in another rows another different dimension matrix?

Hi,
lets say i have a matrix called (Sw) with (60000 x 5) dimension
and another matrix called c1=
c1=[ 3 6 25
4 6 25
5 6 25
3 7 25];
obviously shorter rows than in (Sw)
now i want to remove rows form (Sw) which contain all values of each row of c1
its important to each removed row from (Sw) to include all the values found in the row of c1 and not only one value,
i want the result to be (Sw) but without rows include the values of c1
so as an examples if some of (Sw) looks like this
Sw=[2 (3 6 25) 11===>match(remove)
3 6 7 8 9
(3 6 25) 8 9 ===>match(remove)
(3 6 25) 11 11===>match(remove)
3 4 (5 6 25) ===>match(remove)
4 6 10 11 12
(4 6 25) 13 14===>match(remove)
5 8 13 14 15
5 6 15 16 17
(5 6 25) 20 22===>match(remove)
3 4 7 8 9
3 7 8 9 10
(3 7 25) 33 34]===>match(remove)
so the result (after removing the marked matched row) would be
Sw=[3 6 7 8 9
4 6 10 11 12
5 8 13 14 15
5 6 15 16 17
3 4 7 8 9
3 7 8 9 10]
after removing the rows contains values matched to rows of c1
please help.

 Accepted Answer

Sorry I couldn't come up with any way of doing it without a for loop. Others might know a better way of performing this, but here you go.
for i = 1:abs(size(Sw,2)-size(c1,2))+1;
check(:,i) = ismember(Sw(:,i:size(c1,2)+(i-1)),c1,'rows');
end
Sw1 = Sw(sum(check,2)==0,:);

11 Comments

okay it works 100%..
but lets assume that i have many other smaller matrices other than c1 and different in sizes
such as
c2=[6 9 33 34
7 9 33 34
6 10 33 34
7 10 33 34
6 11 33 34
7 11 33 34];
c3=[3 9 25 33 34
4 9 25 33 34
5 9 25 33 34
3 10 25 33 34
4 10 25 33 34
5 10 25 33 34
3 11 25 33 34];
c4,c5,...,cn
can i include them all in the same loop or should i do a loop for each ?
I would agree with cyclist that I don't think you will be able to avoid looping through the different c arrays. I strongly advice putting them as cells in cell matrix so you can loop through them, rather than picking variable names like c1, c2, c3, ...
c = {c1;c2;,c3;...;cn}; % Might have to fiddle a bit with that syntax, but it should get you started
for j = 1:size(c,1);
for i = 1:abs(size(Sw,2)-size(c{j},2))+1;
check(:,i) = ismember(Sw(:,i:size(c{j},2)+(i-1)),c{j},'rows');
end
Sw1{j} = Sw(sum(check,2)==0,:);
end
you all guys' have been great.
excuse me but am a little bit new to matlab, but how could i return the final (Sw) form the (Sw1) cell after removing all c's ??
Each cell of Sw1 will give you the reduced Sw array for the corresponding c array. If you are trying to just remove all rows of Sw that correspond to any c array, then you can remove the cell indexing from Sw1, and call that variable Sw. This will overwrite the Sw variable each time the outer loop runs, having removed all of the corresponding rows of the c array that was considered.
could you show me the syntax of getting all the indices of all arrays elements stored in (Sw1) cell and how to remove the corresponding indices from the full (Sw) ??
% Replace
Sw1{j} = Sw(sum(check,2)==0,:);
% With
Sw = Sw(sum(check,2)==0,:);
it gave error due to indices on the left side are not compatible with the size of the right side.
at the line of==> check(:,i) = ismember(Sw(:,i:size(c{j},2)+(i-1)),c{j},'rows');
Oh, I forgot about that. It's happening because check is sized to have the same number of elements as the original Sw. One sloppy way of getting around this is to 'clear check' to erase the variable so it can be fit to the proper size again.
okay can you show me the syntax of doing that or tell me the steps if it requires something done manuely cause as i told you am new to matlab ?
c = {c1;c2;,c3;...;cn}; % Might have to fiddle a bit with that syntax, but it should get you started
for j = 1:size(c,1);
for i = 1:abs(size(Sw,2)-size(c{j},2))+1;
check(:,i) = ismember(Sw(:,i:size(c{j},2)+(i-1)),c{j},'rows');
end
Sw = Sw(sum(check,2)==0,:);
clear check % This <<----
end

Sign in to comment.

More Answers (1)

Here is one way:
Sw = [2 3 6 25 11
3 6 7 8 9
3 6 25 8 9
3 6 25 11 11
3 4 5 6 25
4 6 10 11 12
4 6 25 13 14
5 8 13 14 15
5 6 15 16 17
5 6 25 20 22
3 4 7 8 9
3 7 8 9 10
3 7 25 33 34];
c1 = [3 6 25
4 6 25
5 6 25
3 7 25];
[m_Sw,n_Sw] = size(Sw);
[~,n_c1] = size(c1);
hasMatch = false(m_Sw,1);
for ncol = 1:(n_Sw-n_c1+1)
hasMatch = hasMatch | any(all(Sw(:,ncol:(ncol+n_c1-1)) == repmat(permute(c1,[3 2 1]),[m_Sw 1]),2),3);
end
Sw(hasMatch,:) = [];
Annotated version:
% The input matrices
Sw = [2 3 6 25 11
3 6 7 8 9
3 6 25 8 9
3 6 25 11 11
3 4 5 6 25
4 6 10 11 12
4 6 25 13 14
5 8 13 14 15
5 6 15 16 17
5 6 25 20 22
3 4 7 8 9
3 7 8 9 10
3 7 25 33 34];
c1 = [3 6 25
4 6 25
5 6 25
3 7 25];
% Get the necessary sizes of the input matrices
[m_Sw,n_Sw] = size(Sw);
[~,n_c1] = size(c1);
% Preallocate a vector that indicates whether an Sw row has c1 match. (Initialize with no matches.)
hasMatch = false(m_Sw,1);
% For loop that will "slide" c1 along Sw, comparing all possible column combinations
for ncol = 1:(n_Sw-n_c1+1)
% Permute c1 into dimension 3, to facilitate comparing all rows of Sw with all rows of c1, simultaneously
c1p = permute(c1,[3 2 1]);
% Repeat the permuted c1, so that it has the same number of rows as Sw
c1pr = repmat(c1p,[m_Sw 1]);
% Check each row of c1 for a match
thisRowMatches = all(Sw(:,ncol:(ncol+n_c1-1)) == c1pr ,2);
% Check to see if ANY row of c1 matches
anyRowMatches = any(thisRowMatches,3);
% Mark the row as matched, if either there was a prior match, or a new match
hasMatch = hasMatch | anyRowMatches;
end
% Trim the matrix
Sw(hasMatch,:) = [];

7 Comments

yeah it works fine.. but is there a way to include other smaller matrices other than c1 in the same loop which are different in sizes too, such as:-
c2=[6 9 33 34
7 9 33 34
6 10 33 34
7 10 33 34
6 11 33 34
7 11 33 34];
c3=[3 9 25 33 34
4 9 25 33 34
5 9 25 33 34
3 10 25 33 34
4 10 25 33 34
5 10 25 33 34
3 11 25 33 34];
c4,c5,...,cn
or should it be a loop for each ??
I don't see a simple way to avoid looping over your cn variables.
FYI, Bob's algorithm is essentially the same as mine, but certainly more compact and elegant.
But, in some superficial testing on arrays of your size, I found that my method is about 5 times faster than his. So, bear that in mind in case it matter. If you only need to do this a few times, it will not be consequential. Just a 10 seconds or so.
you both guys are great.
i'll put what you said in consideration.
thanks so much :)
I suspected there was a faster way of doing it, but I am not well versed in some of the more advanced matlab commands. What parts of your code make the most difference in speed, and why?
I frankly didn't dig into it. Probably ismember has some overhead and various other inefficiencies, in comparison to the pure math approach that I used.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!