worldterminator
worldterminator

Reputation: 3066

What is the equivalent Python function for "filter" in MATLAB?

I want to do apply a filter function on a vector in MATLAB.

In Python I write:

l = [1,2,3,4]
l2 = filter(lambda x:x>2,l)

How do I write this in MATLAB?

Upvotes: 1

Views: 1724

Answers (2)

Jeremy Gamet
Jeremy Gamet

Reputation: 165

To expand on the example (bonus) answer of @rayryeng :

function out = filter_python(in, func)
    out = in(func(in));
end

This idea could be expanded to whole rows of data in a 2D array.

function out = filtrow(func,in,colnum)
if nargin == 2
   colnum=0;
   sz = size(in);
   if sz(1)==1 || sz(2)==1
      out = in(func(in));
      return
   else
      out = in;
      for i = sz(2):-1:1
          out = out(func(out(:,i)),:);
      end
   end
end
if nargin == 3
  out = in(func(in(:,colnum)),:);
end

Or if you'd prefer by cols.

  function out = filtcol(func,in,rownum)
  if nargin == 2
    rownum=0;
    sz = size(in);
    if sz(1)==1 || sz(2)==1
        out = in(func(in));
        return
    else
        out = in';
        for i = sz(2):-1:1
            out = out(func(out(:,i)),:);
        end
        out = out';
    end
  end
  if nargin == 3
    out = in';
    out = out(func(out(:,rownum)),:);
    out = out';
  end

So given matrix A:

 A =

     0    0.4694    0.1656    0.0838    0.0782    0.8687    0.1818
0.0540         0    0.6020    0.2290    0.4427    0.0844    0.2638
0.5308    0.3371         0    0.9133    0.1067    0.3998    0.1455
0.7792    0.1622    0.6541         0    0.9619    0.2599    0.1361
0.9340    0.7943    0.6892    0.8258    0.0046    0.8001    0.8693
0.1299    0.3112    0.7482    0.5383    0.7749    0.4314    0.5797
0.5688    0.5285    0.4505    0.9961    0.8173    0.9106    0.5499

#%%% We can also remove entire rows or cols by this method
#%%% here we use filtrow to remove rows where elements do no pass the c condition function

>> out = filtrow(@(x) x>0,A)

out =

0.9340    0.7943    0.6892    0.8258    0.0046    0.8001    0.8693
0.1299    0.3112    0.7482    0.5383    0.7749    0.4314    0.5797
0.5688    0.5285    0.4505    0.9961    0.8173    0.9106    0.5499


#%%% Or we can do the same to remove the cols

>> out = filtcol(@(x) x>0,A)

out =

0.0782    0.8687    0.1818
0.4427    0.0844    0.2638
0.1067    0.3998    0.1455
0.9619    0.2599    0.1361
0.0046    0.8001    0.8693
0.7749    0.4314    0.5797
0.8173    0.9106    0.5499

#%%%Or you could filter by individual rows

>> out = filtrow(@(x) x>0,A,1)

out = 

0.0540         0    0.6020    0.2290    0.4427    0.0844    0.2638
0.5308    0.3371         0    0.9133    0.1067    0.3998    0.1455
0.7792    0.1622    0.6541         0    0.9619    0.2599    0.1361
0.9340    0.7943    0.6892    0.8258    0.0046    0.8001    0.8693
0.1299    0.3112    0.7482    0.5383    0.7749    0.4314    0.5797
0.5688    0.5285    0.4505    0.9961    0.8173    0.9106    0.5499

Upvotes: 0

rayryeng
rayryeng

Reputation: 104504

The closest equivalent in MATLAB is to use logical indexing to filter out elements you don't need:

l = [1,2,3,4];
l2 = l(l > 2);

What filter in Python does is that it returns another list given that the predicate you specify for each element in your list evaluates to True. Any elements that are False are removed from the list. On that same token, in MATLAB, you can directly index into an array with logical indexing to give you the same thing.


So what exactly does l2 = l(l > 2); do? Basically, l > 2 gives you an array of True and False that is the same size as l. It will look like this in MATLAB:

>> l = [1,2,3,4]

l =

     1     2     3     4

>> l > 2

ans =

     0     0     1     1

As you can see, l > 2 returns a logical vector that is the same size as l. What is shown here is whether or not each value of l satisfied the predicate of it being greater than 2. As expected, the first two elements are False while the last two elements are True. By using this logical vector as input into your vector l, you are indexing so that any locations that are equal to True in this vector, the corresponding locations in l are selected whereas the locations that are False get filtered out. As such, the first two elements are removed because they are False while the last two elements stay because those locations are True.

Therefore, doing l2 = l(l > 2); thus gives:

>> l2 = l(l > 2)

l2 =

     3     4

Read more about logical indexing here from Steve Eddins's blog: http://blogs.mathworks.com/steve/2008/01/28/logical-indexing/


Bonus

However, if you really want to use the filter paradigm, you can define a function that can do it like so:

function out = filter_python(in, func)
    out = in(func(in));
end

This does no error checking and you need to make sure that func is a function that accepts a vector and that the output is also a vector as the same size as the input vector in. The function also needs to return True/False for each element in the input vector.

Note that I'm calling this filter_python because filter is a function that already exists in MATLAB that's part of the Signal Processing Toolbox. Save this to a file called filter_python.m. Now that you're done, you'd call it like this:

l = [1,2,3,4];
l2 = filter_python(l, @(x) x > 2);

@(x) is an anonymous function, much like lambda x is in Python.


As a bonus, in IPython, this is what we get:

In [13]: %paste
l = [1,2,3,4]
l2 = filter(lambda x:x>2,l)

## -- End pasted text --

In [14]: l
Out[14]: [1, 2, 3, 4]

In [15]: l2
Out[15]: [3, 4]

.... and in MATLAB (as we showed earlier):

>> l = [1,2,3,4];
>> l2 = l(l > 2);
>> l2

l2 =

     3     4

Similarly with the custom function:

>> l = [1,2,3,4];
>> l2 = filter_python(l, @(x) x > 2);
>> l2

l2 =

     3     4

Upvotes: 2

Related Questions