One/zero Matrix, merge subset of columns
2 views (last 30 days)
Show older comments
Say I have this matrix of ones and zeros, 10x6:
x= [ 0 0 0 1 0 0
0 1 1 1 1 1
0 1 1 0 1 1
0 0 0 0 0 0
0 0 0 0 0 0
1 0 0 0 0 0
0 0 1 1 1 1
0 0 0 0 0 1
0 0 0 0 0 1
0 0 0 0 1 1];
I would like to remove the columns that are a subset of any other column. For instance, column 2 is a subset of column 3 (because all ones in column 2 are in the same rows of column 3). Similarly column 3 is a subset of column 6, then columns 3 should be eliminated. At the end only the columns are not "subset" of other should remain only. So in the example, I should get:
0 1 0
0 1 1
0 0 1
0 0 0
0 0 0
1 0 0
0 1 1
0 0 1
0 0 1
0 0 1
The order of te columns is not importan, but the speed.
Any hint will be very much appreciatted. Thanks!
0 Comments
Accepted Answer
Jan
on 16 Dec 2020
Edited: Jan
on 16 Dec 2020
x0 = [ 0, 0, 0, 1, 0, 0; ...
0, 1, 1, 1, 1, 1; ...
0, 1, 1, 0, 1, 1; ...
0, 0, 0, 0, 0, 0; ...
0, 0, 0, 0, 0, 0; ...
1, 0, 0, 0, 0, 0; ...
0, 0, 1, 1, 1, 1; ...
0, 0, 0, 0, 0, 1; ...
0, 0, 0, 0, 0, 1; ...
0, 0, 0, 0, 1, 1];
% Save memory:
x = logical(x0);
for Iter = 1:2 % From left to right and right to left
nCol = size(x, 2);
del = false(1, nCol);
for iCol = 1:nCol
col = x(:, iCol);
for jCol = iCol + 1:nCol
if all(and(col, x(:, jCol)) == col)
del(iCol) = true;
break
end
end
end
x(:, del) = [];
x = x(:, end:-1:1); % Change order
end
Another apporach:
x = logical(x0); % Save memory
nCol = size(x, 2);
del = false(1, nCol);
for iCol = 1:nCol
if ~del(iCol)
col = x(:, iCol);
for jCol = iCol + 1:nCol
if ~del(jCol)
both = and(col, x(:, jCol));
if all(both == x(:, jCol))
del(jCol) = true;
elseif all(both == col)
del(iCol) = true;
break
end
end
end
end
end
x(:, del) = [];
0 Comments
More Answers (1)
Image Analyst
on 13 Dec 2020
Try this. It will give you what you wanted.
x= [ 0 0 0 1 0 0
0 1 1 1 1 1
0 1 1 0 1 1
0 0 0 0 0 0
0 0 0 0 0 0
1 0 0 0 0 0
0 0 1 1 1 1
0 0 0 0 0 1
0 0 0 0 0 1
0 0 0 0 1 1];
[rows, columns] = size(x)
% Initialize an array of the columns we may need to delete.
columnsToDelete = false(1, columns);
for col = 1 : columns
% Get this Column
thisColumn = x(:, col);
% Scan the other columns.
for col2 = col + 1 : columns
otherColumn = x(:, col2);
% And them together and see if it's the same as the first column
anded = thisColumn & otherColumn;
if all(anded == thisColumn)
% It's a subset.
fprintf('Column %d is a subset of column %d.\n', col, col2);
% Log that col is a subset of some other column.
columnsToDelete(col) = true;
end
end
end
% Now delete those columns that were determined to be
% a subset of any of the columns to the right in the array.
xOut = x; % First initialize a copy for the output.
% Now delete the columns we need to.
xOut(:, columnsToDelete) = [] % Setting to null removes the column.
You could also just extract the columns you want, so instead of the last few lines, have this:
% Now take a subset of any of the columns in the array
% by taking the inverse of the logical vector.
xOut = x(:, ~columnsToDelete); % Extract the columns we want.
They're just 2 different ways of getting xOut.
4 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!