one example about arrayfun in matlab - matlab

I am new to matlab. I have the following code like this:
names=arrayfun(#num2str, 1:nseq_all, 'unif', 0);
After searching, I understand that arrayfun applies a function to each element of an array. So, I guess in this case, we apply num2str function to each element of the array 1:nseq_all. 'unif' and 0 are the arguments for the function and the corresponding value part. I have trouble to understand this part. Any comments are greatly appreciated.

'unif',0 is shorthand for 'UniformOutput',false, which means that the output does not have the same dimensions as the input array 1:nseq_all.
This is because a string 1 dimensions 1x1, but 124 has dimensions 1x3.
names will be a cell array, as a normal numeric array can't contain rows/columns with different numbers of elements.
Be sure to carefully read the arrayfun documentation.

'unif', 0 is shorthand for 'UniformOutput',false. Note that parameterName/parameterValue pairs in Matlab allow the abbreviation of the parameterName, as long as it doesn't conflict with another possible parameter. In this case 'un',0 would have worked as well. Anyway, what is that option for?
modifiedArray = arrayfun(function_handle, array)
applies the function defined in function_handle to each element of array and returns modifiedArray, which is the same size as array, and the class of whatever function_handle returns. This syntax can only be used if the output of function_handle is scalar, though class doesn't matter, so the output of function_handle can be a scalar structure, i.e. arrayfun(#(x)struct('field',x),magic(4)) is valid.
cellArray = arrayfun(function_handle, array, 'UniformOutput', false)
applies the function defined in function_handle to each element of array and returns cellArray, which is the same size as array. Each element of cellArray contains the output of a call of function_handle. This syntax must be used if the output of function_handle is non-scalar (even if each calculation returns a 1-by-2 array, which is totally uniform), but of course, you can use it with scalar output as well.
In your case, num2str returns a character array which is non-scalar if the argument of num2str goes above 9. Consequently, you need to set UniformOutput to false.

Related

Generalise calling of Matlab function with generic number of inputs

Suppose I have a pre-built Matlab function
function A=f(varagin)
...
end
I call f.m in a file main.m.
When calling f.m, the inputs to include depend on the number of columns of two matrices X and Y.
For example, if
d=2;
X=randn(4,d);
Y=randn(4,d);
then
A=f(X(:,1),X(:,2),Y(:,1),Y(:,2));
If
d=3;
X=randn(4,d);
Y=randn(4,d);
then
A=f(X(:,1),X(:,2),X(:,3),Y(:,1),Y(:,2),Y(:,3));
If
d=4;
X=randn(4,d);
Y=randn(4,d);
then
A=f(X(:,1),X(:,2),X(:,3),X(:,4),Y(:,1),Y(:,2),Y(:,3),Y(:,4));
Could you help me to generalise the calling of f.m in main.m with any d?
The answer is more or less identical to that of your previous question about indexing:
args = {arg1, arg2, arg3};
f(args{:});
args{:} generates a comma-separated list of its elements, which is thus equivalent to using each of its elements as an argument to the function.
To convert the columns of a numeric matrix to a cell array, use mat2cell.

How to initialize a Matlab struct array for growing?

Growing an array, e.g. through x = [x, a] in a loop, is usually frowned upon in Matlab programming, because it leads to one or more resize operations, and therefore preallocation is usually the better option. However, in some contexts, for example as a reduction assignment in a parfor block, it can have advantages. For that purpose, the array has to be created as zero-size. For numerical arrays, the expression for that is [], for cell arrays {}.
For struct arrays, it is not so clear cut. For example initialization as struct() does not create a zero-size struct array, but a 1x1 struct array with no fields. This leads to the error
Error using horzcat
Number of fields in structure arrays being concatenated do not match.
Concatenation of structure arrays requires that these arrays have the same set of fields.
while growing, because the field structure of appended structs is incompatible with the "no fields" struct.
How to initialize a zero-size struct array for growing?
Growing an array by concatenation
x = [x, 0];
is very slow, see here and here. Instead, one should (if pre-allocation is not possible for whatever reason), grow an array by appending a new element like so:
x(end+1) = 0;
The reason is that [x,0] creates a new array, copying the old data into it, at every single loop iteration, whereas the other form extends the array, needing reallocation only occasionally (it doubles the underlying memory size when the array becomes too small).
To initialize an empty struct array (as suggested by #LuisMendo in a comment) one can do this:
s = struct('field1', {}, 'field2', {});
To append to it, do:
s(end+1) = struct('field1', 1, 'field2', 'x');
Alternatively, one can append by
s(end+1).field1 = 5;
s(end).field2 = 'y';
Note that in this case, end+1 only happens when first appending a new element to the array, subsequent fields are written to the last array element.
It turns out the answer is to initialize to a zero-size numeric array, x = []. Even though it is not a struct array, appending a struct a via x = [x, a] generates a 1x1 struct array, to which further structs with the same fields can be appended.
This unintuitive behavior seems to be a general quirk of the Matlab language, in that [] is of "flexible type". It is initially a zero-size array of doubles, but appending singles makes it a single array, and appending cell arrays makes it a cell array.
As #LuisMendo pointed out in the comments, struct([]) directly gives a zero-size struct array with no fields. This syntax may be preferred because it is less ambiguous. Moreover, s = struct('field1', {}, 'field2', {}) may be used to create a zero-size struct array with defined fields.
I just found that #CrisLuengo's proposal in the comments, appending by assignment to end + 1 instead of concatenation, does not work in the context of the question, "initialize for growing". Assignment cannot change the "type" of the struct, which is defined by its fields. Changing from no fields to the fields of whatever struct is to be appended leads to the error "Subscripted assignment between dissimilar structures."
(but see his comment and my answer for clarification)

Array as a function parameter instead separate variables in Matlab

I need pass to a function (jacobian() in my case) a symbolic variable array is being creating dynamically. Say,
jacobian(handles{2}(t,y,paramlist),y)
where paramlist=[var1, var2, var3, ..., varN] has an arbitry size. All variables here are symbolic and have various names. MATLAB throw an error:
Not enough input arguments.
Knowing number of parameters in the function definition one can pass all parameters separately. Say, for n=3:
jacobian(handles{2}(t,y,paramlist(1),paramlist(2),paramlist(3)),y)
But what about the common case? It's a bad style of programming to write the function call for each fixed number of parameters. Is there a way to pass an array so as it would be treated as distinct variables?
You can convert paramlist to a cell array (using num2cell) and then use {:} indexing to create a comma separated list which you can then use this for indexing into handles{2}. This will make it such that each value of paramlist is passed as a separate subscript.
plistcell = num2cell(paramlist);
jacobian(handles{2}(t, y, plistcell{:}), y)

matlab function for sum of n number of input?

I am new to matlab. This might be a silly question.
The problem says:
Write a function sum_var which takes variable number of scalar inputs & returns their sum
E.g.
sum_var(2,4,6)
ans =
16
I tried varargin,nargin however i cant manipulate those commands to get a desired output.
If you want to have a function that takes several scalar inputs and give you their sum, then do the following:
function result = sum_var(varargin)
result = sum(cell2mat(varargin));
end
The problem you have is that varargin is a cell array and you have to transform it to a matrix array (using cell2mat()) before using the sum() function on it.

What is the meaning of this command

capi = cell2mat(arrayfun(#(b) sum(resulti == b,1),nonzeros(unique(resulti)), 'UniformOutput', false))
why when I used that code, my code cannot run and there was command like the following command?
??? Array dimensions must match for binary array op.
All this can be found via Matlab's documentation, which should always be your first step!
Having said that, here's a breakdown of your command:
cell2mat: convert a cell array to a matrix according to some format you define
arrayfun: evaluate some function for all elements in an array. The function may be an anonymous function (e.g., #(b) sum(resulti == b,1))
sum: sum all the elements of a matrix in a particular direction. Direction 1: down the rows, direction 2: along the columns, etc.
nonzeros: form new array by removing all zeros from the input array. This will output a column vector, irrespective of the input's shape.
unique: return the input array with all duplicates of all values removed. The output will also be sorted.
Type help [command] or doc [command] for more information on all these commands (which I recommend you do!)
Now, combining these into your command:
A = nonzeros(unique(resulti))
will return all unique entries in a column vector, with any zero removed.
B = arrayfun(#(b)sum(resulti==b), A, 'UniformOutput', false)
will run the function #(b) sum(resulti == b,1) on all entries of the newly created column vector A, and collect them in a cell-array B (cell, because 'UniformOutput' is set to false). This function will simply compare each element of resulti against the running index b, and find the total count along the rows. Then, finally,
capi = cell2mat(B)
will convert the cell-array B back to a normal Matlab array.
The objective of this command seems to be to count the number of non-unique occurrences on each of the colums of resulti. As hinted at by #GuntherStruyf, this whole command seems a hacked-together, forced one-liner, rather than well-manageable, readable code. I would personally opt to break it over several lines, avoid arrayfun (slow) and instead use bsxfun or a for-loop (faster (yes, also the for-loop), better readable).
But that's a matter of opinion (which goes against popular opinion :)