Skip to Main Content Skip to Search
File Exchange
MATLAB Newsgroup
Link Exchange
  Blogs  
 Contest 
MathWorks.com

Loren on the Art of MATLAB

March 1st, 2006

More on expansion: arrayfun

Since there seems to be so much interest in the topic of going beyond scalar expansion, it seems worth talking about yet some other ways to achieve the same goals. I am very appreciative of the thoughtful comments we've received so far on this topic and I know we will be weighing this input carefully as we design how to move forward.

Suppose we want to raise all the values in x to all the powers in powers, where both x and powers are vectors, like this:

powers = 1:3;
x = (0:.1:.4)';

We know from the last blog article, we can achieve this by creating larger intermediate arrays like this, using Tony's trick (used for most of the work in repmat:

X = x(:,ones(size(powers,2),1))
P = powers(ones(size(x,1),1),:)
X =

         0         0         0
    0.1000    0.1000    0.1000
    0.2000    0.2000    0.2000
    0.3000    0.3000    0.3000
    0.4000    0.4000    0.4000

P =

     1     2     3
     1     2     3
     1     2     3
     1     2     3
     1     2     3

and then we are ready to perform the desired calculation:

q = X.^P
q =

         0         0         0
    0.1000    0.0100    0.0010
    0.2000    0.0400    0.0080
    0.3000    0.0900    0.0270
    0.4000    0.1600    0.0640

but at the cost of 2 larger arrays, X and P, that we might not even need going forward.

In the absence of new operators in MATLAB 7, how might we solve this today without creating these temporary arrays and without using a for loop? A new feature in R14sp3, arrayfun is a good candidate. Here are two ways to achieve the same results using arrayfun, the first iterating calculating results for each value of x and the second, for each value of powers. I am taking advantage of anonymous functions, new in MATLAB 7, to define the function I want to calculate, first as a function of powers, and second, as a function of the x values.

pq = cell2mat(arrayfun(@(p)x.^p,powers,'uniformoutput',false));
xq = cell2mat(arrayfun(@(x)x.^powers,x,'uniformoutput',false));

Before proceeding, let's just make sure we're getting the right answer!

isequal(xq,pq,q)
ans =

     1

Now that we've taken care of checking for correctness, let's decipher what the statements mean. Taking the final arguments to arrayfun first, I chose nonuniform output since for each value of my function, I calculate a vector of output values, not a single value. This places outputs for each input value (in this case, the values in powers), into cells in a cell array.

The first argument is an anonyous function, a function defined "inline" that takes its non-argument values from the workspace. So the first function, @(p)x.^p, takes x from the workspace. The function itself takes the values in x and raises them each to some value p, the function argument. Then with the second input to arrayfun, we set the argument to be iterated over to powers from our workspace.

Finally, since our output is now in a cell array, in this case with each cell containing equal numbers of elements, we convert the cell array to a numeric matrix using cell2mat.

Which of the 2 methods using arrayfun is preferable? Well, as is so often, that depends. Since there's an intermediate cell array, we might want to minimize its size. How large are typical sizes for the vectors x and powers? If one is typically substantially larger than the other, we might want to profile the code, either from the command line or the desktop (see this link for information about using the MATLAB Profiler user interface). The profiler can help us make these tradeoffs.

Once again I ask for you to add your thoughts here. Thanks.

6 Responses to “More on expansion: arrayfun”

  1. Petr Pošík replied on :

    Hi Loren. Thanks for introducing the arrayfun to me! I’m using SP2 so that I can’t use them, but anyway…

    Yes, this is a reasonable way of accomplishing the expansion. Similar constructs can be found in PERL (function map), etc.

    But one reason for which I love MATLAB so much is the minimalism with which these things can be written. And I think the arrayfun is not the MATLAB way of doing it. Compare:

    > 5 + [6 7 8 9]

    with

    > arrayfun(@(p)5+p,[6 7 8 9],’uniformoutput’,true)

    Of course, this is a stupid example, but I really do not know if I fell in love with MATLAB if I had to write the second type of commands. The difference when compared with FOR loops is not that big, and in my opinion, the FOR loops are for many programmers more intuitive because they are used to use them.

  2. A Brook replied on :

    This is one point where Mathematica beats you. Their “Outer” is much cleaner and easier to use than this “arrayfun”.

    Why can’t we have Outer in Matlab? Then we can say
    Outer(@(a,b)a.^b,x,powers) — so much easier, nicer, and keeping with Matlab Spirit.

    Maybe you can somehow implement Outer with arrayfun?

  3. StephenLL replied on :

    The approach recommended by Urs in Loren’s previous blog entry, would yield something like: genopfun(x,y.’,'^’) (if x and y were vectors) which is really nice and compact. Simililar to R’s outer function. What makes the genop solution so nice is that rather then just vectors it would work along singleton dimensions as well.

    Stephen

  4. Dani Hak replied on :

    Hello Loren,

    arrayfuncion works on each array element,
    is there a function which operates on each colon?

    Thanks,
    Dani.

  5. Loren replied on :

    Dani-

    No, there is not function per se that works on each column. However, many MATLAB functions do operate on columns such as sum, mean, fft. You could write an anonymous function that takes a matrix and works on each column (using something like A(:,i) ). If you have a detailed question, I recommend you contact technical support to help with the specific issues.

    –Loren

  6. StephenLL replied on :

    Dani,

    The following maybe what you are looking for.
    http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=16467&objectType=FILE

    I wrote it so I did not have to explicitly write loops or always write code that could take dim as an input.

    The benefit is not speed but clear compact writing of code.

    StephenLL

Leave a Reply


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Ulla Vainio: That error bar width adjustment was extremely useful and I would never have figured it out myself....
  • Peter Perkins: Jessee, there is a property that you can use to tag variables with units. For example, >> load...
  • Jessee: I could potentially see myself using dataset for casually looking at data, but from an application standpoint...
  • Loren: Oktay- It very much depends on the details of the calculations you are doing. Vectorization can sometimes...
  • Oktay: Hello, Is there any significant difference between using: - Vectorization inside a subfunction - Benefiting...
  • Loren: Clare- Yes, sum can sum a double vector: x = [.3 .4 pi/3] y = sum(x) x = 0.3 0.4 1.0472 y = 1.7472 You must...
  • Clare J: R2007a - Student Version When I use sum to sum a vector of type double I get this error message: ???...
  • Sarah Zaranek: Hi Jacob, Sorry about the slow response. You are correct that the code would be slower without the...
  • Navaneethan Santhanam: Thanks a lot, Loren! That worked perfectly.
  • Mike N: Should it be OK to use “persistent 221; variables in a deployed application? What if I have two...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.

Related Topics