Home > Software engineering >  Matlab cellfun with differently-sized input arrays
Matlab cellfun with differently-sized input arrays

Time:10-22

How can I use cellfun (or appropriate alternative) when the input arrays are different sizes, and get all combinations of results (i.e., evaluated for the cross join of the arrays)?

This example uses a dummy function; the actual function is more complicated, so I'm looking for answers that call a custom function. Using Matlab R2018a, so I'm looking for an answer that is compatible with that.

a = 0:0.1:0.3; b = 100:5:120;

test = cellfun(@(x,y) myfunc(x,y,0), num2cell(a), num2cell(b));

function [result] = myfunc(i, j, k)
    % k is needed as fixed adjustment in "real life function"
    result = 0.1 * i   sqrt(j)   k;
end

The above code returns the following error:

Error using cellfun
All of the input arguments must be of the same size and shape.
Previous inputs had size 4 in dimension 2. Input #3 has size 5

The expected output from this example is the "result" column below; i and j are shown for convenience.

i j result
0 100 10
0.1 100 10.01
0.2 100 10.02
0.3 100 10.03
0 105 10.24695077
0.1 105 10.25695077
0.2 105 10.26695077
0.3 105 10.27695077
0 110 10.48808848
etc etc etc

CodePudding user response:

The answer here is bsxfun. A worked example is below.

% You need a function with the correct number of inputs.
% With your sample, I would do something like this.
myfunc       = @(i,j,k) 0.1 * i   sqrt(j)   k;
myfunc_inner = @(i,j) myfunc(i,j,0);
%    Side not: using separate files for functions is more 
%    efficient, but makes for worse examples on stackoverflow

%Setting up the inputs    
a = 0:0.1:0.3;
b = 100:5:120;

%bsxfun, for two inputs, is called like this.
c = bsxfun(myfunc_inner, a', b)

bsxfun does the following:

  • Expands scalar dimensions of the inputs so that they match
  • Performs element-wise combinations of the inputs, using the provided function input

In this case, the result is:

c =
           10       10.247       10.488       10.724       10.954
        10.01       10.257       10.498       10.734       10.964
        10.02       10.267       10.508       10.744       10.974
        10.03       10.277       10.518       10.754       10.984

To get the input in the form you requested, simply run c(:).


Historical note:

Back in the time-before-time, we had to use bsxfun more often. Now Matlab expands single dimensions without notice when we perform simple operations on numbers. For example, I used to use the following style frequently:

a = [1 2 3];
b = [4 5 6];

c = bsxfun(@plus, a', b)

Whereas now we simply write:

c = a'   b
  • Related