Computation using cellfun

Cell arrays are useful means of holding various types and sizes of information (as are structs). When manipulations or computations need to be performed on all or a subset of values in a cell array, one useful function that can be utilized is cellfun . Similar to other functions such as structfun or arrayfun, cellfun allows you to apply a predefined or user defined function to each element in the array.

Lets create a cell array of greetings:

>> greetings = {'Hello','Guten Tag','Sawadee','Bonjour','Namaste',''}

If you want to find all nonempty components (or indices) of the array, you can run the following:

>>find(~cellfun('isempty',greetings))

ans =
     1     2     3     4     5

Want to determine the length/size of the components? These built in functions work exactly as their common counterparts.

>> cellfun('size',greetings,2)
>> cellfun('length',greetings)

ans =
     5     9     7     7     7     0

Among some of the other built in functions that can be performed include: ‘isreal’, ‘islogical’, ‘ndims’, ‘prodofsize’,’isclass’

Along with string arrays, cellfun can allow for easier array manipulation, without the use of loops. Take for example the following cell array:

>> A = {magic(3) eye(3) rand(4,3)}

A = 
    [3x3 double]    [3x3 double]    [4x3 double]

If we wanted to transpose each of the individual arrays, we can utilize the transpose and cellfun functions in combination.

>> Btrans = cellfun(@transpose,A,'UniformOutput',false)

Btrans = 
    [3x3 double]    [3x3 double]    [3x4 double]

By default ‘UniformOutput’ is set to true, but in this case we want to set it to false, in order to output the results into another cell array. In case the output of each array will be a scalar, we can leave ‘UniformOutput’ as true. For example see the following results of running sum on each of the arrays, based on different values for ‘UniformOutput’.

>> Bsum = cellfun(@(x) sum(sum(x)),A,'UniformOutput',false)

Bsum = 
    [45]    [3]    [7.3668]

>> Bsum = cellfun(@(x) sum(sum(x)),A)

Bsum =
   45.0000    3.0000    7.3668

Combining num2cell with cellfun can allow for further matrix math.
For example matrix multiplication can be performed on each column of the following array:

>> C = num2cell(rand(3,10),1) 

C = 
    [3x1 double]    [3x1 double]    [3x1 double]    [3x1 double]    [3x1 double]

>> Ctimes = cellfun(@(x) A{1}*x,C,'UniformOutput',false)

Ctimes = 
    [3x1 double]    [3x1 double]    [3x1 double]    [3x1 double]    [3x1 double]

Finally, lets say you have created the following function in order to determine an array’s sum, average, and minimum value:

function [sumArray averageArray minArray] = arraystuff(inputArray)

sumArray = sum(sum(inputArray));
averageArray = mean(mean(inputArray));
minArray = min(min(inputArray));

You are able to pass this function (as well as any other pertinent functions) through cellfun. Therefore in this case, we would have 3 outputs for each component of our initial cell array A:

>>[Asum Aavg Amin] = cellfun(@arraystuff,A)

Asum =
   45.0000    3.0000    7.3668

Aavg =
    5.0000    0.3333    0.6139

Amin =
    1.0000         0    0.0975

Please feel free to comment or provide more examples of cellfun, as you run across this useful command.

7 thoughts on “Computation using cellfun

  1. if there is a cell:a={rand(2,2,2),’hello’,pi;17,1+i,magic(5)}. so, can you tell me the difference about “size” and “length”? i can’t understand the result of b=cellfun(‘length’, a) , c=cellfun(‘size’,a,1), d=cellfun(‘size’,a,2). i don’t know what is the kth dimension of cellfun(‘size’,c,k) in this example. waitting for you answer and thanks a lot.

    • Suigr,

      The cell array ‘a’ that you have created would have 6 cells, with 2 rows and 3 columns (to see that, run ‘size(a)’).

      For your (1,1) entry, i would recommend changing the 3-dimensional array to be rand(2,4,3), so you can better see what the outputs represent.

      b = cellfun(‘length’,a) returns the larger dimension length of each cell in the array a. In the example you provided:
      b =
      2 5 1
      1 1 5
      If you changed your (1,1) entry to be a{1,1} = rand(2,4,3), and reran b = cellfun(‘length’,a), the answer would change slightly:
      b =
      4 5 1
      1 1 5

      The string in a(1,2) has 5 characters, thus b returns 5, and the numbers return 1, as they have one dimension.

      As for cellfun(‘size’,a,k), each dimension k is returned for each entry in the cell array. If k = 1, you would see the size along each row:
      c =
      2 1 1
      1 1 5
      if k = 2, the size of each column
      d =
      4 5 1
      1 1 5
      As all other cells have a maximum of 2 dimensions (rows and columns), k > 2 will always return 1 for their size. Hope this helps. Again, try to make non-square matrices to see how size and length work.

  2. My favorite use of cellfun is when I combine it with regexp.


    Fnames = fieldnames(ExampleStruct);
    idx = find(cellfun(@(x)~isempty(x),regexp(Fnames, [StatType '_'])));

    Above code should give the index for fields in the structure that I’m interested in (i.e. fields that share [StatType ‘_’] pattern.). I use this when I convert the structure to array/cell.

Leave a Reply

Your email address will not be published. Required fields are marked *