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