7

I would like to remove some columns and rows from a big matrix. Those are the columns and the rows which have all zeros values. Is there any function in MATLAB that can do it for you quite fast? My matrices are sparse. I am doing this way:

 % To remove all zero columns from A
 ind = find(sum(A,1)==0) ;
 A(:,ind) = [] ;

 % To remove all zeros rows from A
 ind = find(sum(A,2)==0) ;
 A(ind,:) = [] ;

It would be nice to have a line of code for this as I may do this kind of task repeatedly. Thanks

Yas
  • 811
  • 4
  • 11
  • 20
  • 1
    Your code looks good. If your matrices are sparse it may be faster though when you copy the non-zero elements (don't know, just a guess): `B = A(~ind,:)`. – Matthias W. Feb 15 '16 at 10:07
  • Possible duplicate of [Removing zeros from a matrix - Not Sparse](http://stackoverflow.com/questions/738438/removing-zeros-from-a-matrix-not-sparse) – GameOfThrows Feb 15 '16 at 10:13
  • 1
    using `all(A,1)` or `all(A,2)` might be faster than `sum(A,1)`, but I didn't check. – Max Feb 15 '16 at 10:14
  • 1
    Thanks. You are right, I was checking `any` and `all`. The best option seems to be this: `A(:,~any(A)) = []` (to remove zero columns) and `A(~any(A'),:) = []` (to remove all zero rows). Please confirm – Yas Feb 15 '16 at 10:19
  • 2
    @Yas I would think `A(~any(A,2),:) = []` would be faster than `A(~any(A'),:) = []`. You might also want to try `A = A(any(A,2),:)` rather as the `=[]` can be slower: http://stackoverflow.com/questions/12421345/deleting-matrix-elements-by-vs-reassigning-matrix – Dan Feb 15 '16 at 10:21
  • Thanks, `A(~any(A,2),:) = []` was a very good comment, also the follow-up comment. But honestly, both are good enough. Thanks alot guys problem solved! – Yas Feb 15 '16 at 10:29
  • 1
    @GameOfThrows: I don't see this question being a duplicate. The other question addresses removing all zeros. – Daniel Feb 15 '16 at 14:23
  • @Daniel Sorry, I flagged because the OP was already summing the matrix into a vector, and simply referred the question because it has solutions on removing zeros from a vector. – GameOfThrows Feb 15 '16 at 14:38

2 Answers2

10

A single line of code would be:

A=A(any(A,2),any(A,1))

There is no need to use find like you did, you can directly index using logical vectors. The any function finds the rows or columns with any non-zero elements.

Daniel
  • 36,610
  • 3
  • 36
  • 69
2

1 Dimension:

I'll first show a simpler example based on another duplicate question, asking to to remove only the rows containing zeros elements.

Given the matrix A=[1,2;0,0];

To remove the rows of 0, you can:

  • sum the absolute value of each rows (to avoid having a zero sum from a mix of negative and positive numbers), which gives you a column vector of the row sums.

  • keep the index of each line where the sum is non-zero.

in code:

A=[1,2;0,0];
% sum each row of the matrix, then find rows with non-zero sum
idx_nonzerolines = sum(abs(A),2)>0 ;
% Create matrix B containing only the non-zero lines of A
B = A(idx_nonzerolines,:) ;

will output:

>> idx_nonzerolines = sum(abs(A),2)>0
idx_nonzerolines =
     1
     0
>> B = A(idx_nonzerolines,:)
B =
     1     2

2 Dimensions:

The same method can be used for 2 dimensions:

A=[ 1,2,0,4;
    0,0,0,0;
    1,3,0,5];

idx2keep_columns = sum(abs(A),1)>0 ;
idx2keep_rows    = sum(abs(A),2)>0 ;

B = A(idx2keep_rows,idx2keep_columns) ;

outputs:

>> B = A(idx2keep_rows,idx2keep_columns)
B =
     1     2     4
     1     3     5

Thanks to @Adriaan in comments for spotting the edge case ;)

Hoki
  • 11,637
  • 1
  • 24
  • 43
  • Which could be one-lined as `B = A(sum(A,1)>0,sum(A,2)>0)`. I'm interested to see the timing difference between pure logic (`any` and `all`) and `sum`. – Adriaan Sep 12 '19 at 09:03
  • 1
    Definitely, although the other answer is already a one liner and is technically very close to my answer (different function called but same principle involved). So I thought to make it more different I would explain the process a bit more without taking all the shortcuts. – Hoki Sep 12 '19 at 09:07
  • 1
    @Adriaan, thanks, I overlooked the edge case indeed. – Hoki Sep 12 '19 at 12:03