Asked by Noah Chrein
on 1 Jul 2015

say I have an array that I want to run a function over each of its elements, I could easily do this with arrayfun(@f,v) where f is my function name and v is my vector.

But now say f is defined to take two input arguments, that is f(e,k) where e is an element of the same type as in the vector and k is something unrelated to the vector (for example an integer). how can I run arrayfun?

I would want to do this: arrayfun(@f,v,k), however, this runs arrayfun over two vectors v and k.

%%

Example:

Say mv = movingAvg(v,w) takes a vector v and does a moving average filter over it with width w, and returns the filtered vector to mv. Now say A = {v1,v2,...,vn} is an array of vectors. how could I use arrayfun to give me an array mA = {mv1,mv2,...,mvn} such that mvi = movingAvg(vi,10)?

I would assume that maybe mA = arrayfun(@movingAvg,A,10) or mA = arrayfun(@movingAvg,[A 10]) or something of that sort, but this is not true.

Answer by Steven Lord
on 1 Jul 2015

Accepted Answer

This isn't the most efficient way to write "y = x+17" but it's good for demonstration.

k = 17;

x = 1:10;

y = arrayfun(@(z) plus(z, k), x)

Noah Chrein
on 1 Jul 2015

so what's happening in this code is that @(z) is telling array fun to run over z, then you specify the function plus to say "run plus over z", then x is plugged into z?

Is this how it should be interpreted? Thank you for the swift and simple answer,

John D'Errico
on 1 Jul 2015

Well, I'd argue not really. A simple interpretation is that

@(z) plus(z,k)

is an anonymous function, that is passed the argument k from your workspace, as a constant. This function is a function though of only ONE argument: z. Arrayfun thus sees a function of one argument only, so it is happy. That ancillary argument, k, is a constant as far as arrayfun is concerned. arrayfun does not care where a constant comes from, only that it is predefined.

Steven Lord
on 1 Jul 2015

@(z) plus(z, k) is a function [an anonymous function, if you want to be technical] that accepts one input, z, and calls the PLUS function with two inputs, z and k. Since k was defined when this anonymous function was created, and k does not appear in the list of input arguments, the anonymous function "remembers" the existing value.

ARRAYFUN requires the function you pass into it as the first input to accept one input per array over which it should iterate. I passed in one array, x, and so ARRAYFUN will call the function with one input. So the anonymous function satisfies ARRAYFUN's requirements. The PLUS function required you to specify two input arguments, and the anonymous function satisfied that requirement as well. So ARRAYFUN is happy, PLUS is happy, MATLAB is happy, and you're happy because your code runs :)

Sign in to comment.

Answer by Céldor
on 15 Sep 2016

Edited by Céldor
on 16 Sep 2016

I might be a little too late with an answer. However, I had recently a similar problem. I needed to test if vectors contain NaNs or zeros. I thought I would make an anonymous function with arrayfun and used an extra parameters as another function to apply, e.g. isnan(x) or my custom function iszero(x,tol) etc. The problem was a custom function because it needed tolerance to apply. I made something simple below:

iszero = @(x,tol) x < abs(tol) & x > -abs(tol);

I sorted it out everything using varargin:

TEST = @(sw, fun, varargin) arrayfun(@(x) fun(x,varargin{:}), sw, 'UniformOutput',true);

The great thing about varargin is that it is a cell. Even if it's used inside another function as a parameter, when it's empty MATLAB function simply ignores it. I can now use isnan(x) as well as iszero(x,tol) as follows:

a = [0.1 0.01 0.001 0.0001 0.000001];

TEST(a,@isnan)

ans =

0 0 0 0 0

TEST(a,iszero,0.1)

ans =

0 1 1 1 1

TEST(a,iszero,0.001)

ans =

0 0 0 1 1

Hope it helps :)

Sign in to comment.

Answer by Adam
on 1 Jul 2015

Edited by Adam
on 1 Jul 2015

f = @(x,y) x.^2 + y.^2

g = @(x) f(x,3);

a = [1 2 3 4 5];

res = arrayfun( g, a );

is a general example that should give you the syntax you need. You bind a constant to your function handle rather than passing it as an argument to arrayfun so effectively your function, f, of 2 variables is replaced by a function, g, of one variable.

Edit: Note the @(x) part was missing from the definition of g when this was first posted.

Steven Lord
on 1 Jul 2015

You missed a piece of the definition of g. As written, if x is defined before g is defined then g will no longer be an anonymous function handle by the time you get to the ARRAYFUN call and so ARRAYFUN will error. If x is not defined when you define g, you will receive an undefined function or variable error. The definition of g should be:

g = @(x) f(x, 3);

If you're more familiar with C++, think of this technique as similar in some ways to std::bind1st or std::bind2nd.

Adam
on 1 Jul 2015

Sign in to comment.

Answer by saadani seifeddine
on 13 Mar 2017

[B1,...,Bm] = arrayfun(@(x) func(x,var1,...,vark),A1,...,An)

...

function[Y]=func(X,Var1,...,Vark)

...

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.