tags:

views:

1659

answers:

4

I have a matrix

x = [0 0 0 1 1 0 5 0 7 0]

I need to remove all of the zeros such as

x=[1 1 5 7]

The matrices I am using are large (1x15000) I need to do this multiple times (5000+)

Efficiency is key!

+6  A: 

One way:

x(x == 0) = [];

A note on timing:

As mentioned by woodchips, this method seems slow compared to the one used by kts. This has also been noted by Loren in one of her MathWorks blog posts. Since you mentioned having to do this thousands of times, you may notice a difference, in which case I would try "x = x(x~=0);" first.

WARNING: Beware if you are using non-integer numbers. If, for example, you have a very small number that you would like to consider close enough to zero so that it will be removed, the above code won't remove it. Only exact zeroes are removed. The following will help you also remove numbers "close enough" to zero:

tolerance = 0.0001;  % Choose a threshold for "close enough to zero"
x(abs(x) <= tolerance) = [];
gnovice
This fails on negative numbersTry `abs(x)<= tolerance`
KitsuneYMG
The x <= tolerance would exclude negative floating point numbers. You would probably need to expand the comparison to be x >= tolerance and x <= tolerance. The operator for logical and in matlab escapes me at this moment.
Bill Perkins
I corrected the answer to remove any value close enough to zero from either the negative or positive direction.
gnovice
+6  A: 

Just to be different:

x=x(x~=0);

or

x=x(abs(x)>threshold);

This has the bonus of working on complex numbers too

KitsuneYMG
+2  A: 

Here's another way

y = x(find(x))

I'll leave it to you to figure out the relative efficiency of the various approaches you try -- do write and let us all know.

High Performance Mark
+4  A: 

Those are the three common solutions. It helps to see the difference.

x = round(rand(1,15000));

y = x;

tic,y(y==0) = [];toc

Elapsed time is 0.004398 seconds.

y = x;

tic,y = y(y~=0);toc

Elapsed time is 0.001759 seconds.

y = x;

tic,y = y(find(y));toc

Elapsed time is 0.003579 seconds.

As you should see, the cheapest way is the direct logical index, selecting out the elements to be retained. The find is more expensive, since matlab finds those elements, returning a list of them, and then indexes into the vector.

woodchips
Wow! Are those numbers right? I could have sworn that "y(y==0)=[];" and "y=y(y~=0);" were comparable to each other speed-wise. I'll have to check my numbers again.
gnovice
Never mind... I just found a blog post by Loren at the mathworks that addresses exactly this problem, and it seems to agree with your numbers.
gnovice

related questions