How to create an empty array in a matrix - matlab

How to create an empty array in matlab that accepts elements from a matrix when you do not know the no.of elements it is going to contain ?

Use the [] operator. Example:
x = [];
If you wanna be specific in the type of the empty matrix, use the empty property. Examples:
emptyDoubleMatrix = double.empty; % Same as emptyDoubleMatrix = [];
emptySingleMatrix = single.empty;
emptyUnsignedInt8Matrix = uint8.empty;
This works for empty matrices of classes as well. Example:
emptyFunctionHandleMatrix = function_handle.empty;

You can use the empty matrix/vector notation, [], and Matlab will set up a placeholder for it.
x = []
Now if you want to append a scalar, say num, to it, you cannot index it because it is empty.
However, you can either:
Use array concatenation to concatenate itself with another scalar:
x = [x num]
Use the end+1 notation, to address the first available location:
x(end+1) = num
Both of the above two notations also work when you want to append a row or a column vector to an existing row vector or column vectors. But when you are concatenating vectors/matrices, remember to be consistent with the dimensions.

Related

Extracting field from cell array of structure in matlab

I have a cell array (let's say size 10) where each cell is a structure with the same fields. Let's say they all have a field name x.
Is there a way to retreive in a vector the value of the field x for all the structure in the cell array? I would expect the function to return a vector of size 10 with in position 1, the value of the field x of the structure in cell 1 etc etc...
EDIT 1:
The structure in the cell array have 1 field which is the same for all but some others which are different.
First convert your cell array of structures, c, (with identical field names in the same order) to a structure array:
c = cell2mat(c)
Then, depending on the data types and sizes of the elements of the field, you may be able to use
[c.x]
to extract your vector of field x values in the "standard" way.
It is also possible that you can skip the conversion step and use cellfun(#(e)e.x, c) to do the extraction in one go.
The below code creates a cell array of structures, and extracts field 'x' of each structure to a vector v.
%create a cell array of structures
s1.a = 'hello';
s1.x = 1;
s2.a = 'world';
s2.x = 2;
c{1} = s1;
c{2} = s2;
v = zeros(1,2);
%extract to vector
for idx=1:size(c,2)
v(1,idx) = c{idx}.x;
end
Let's say you have
c = {s1, s2, s3, ...., sn};
where common field is 'field_1', then you have two options
Use cell2mat.
cc = cell2mat(c); % which converts your cell array of structs into an array of structs
value = [cc.field_1]; % if values are number
or
value = {cc.field_1}; % if values are characters, for example
Another option is to use cellfun.
If the field values are characters, you should set "UniformOutput" to "false"
value = cellfun(#(x) x.field_1, c, 'UniformOutput', false)
The first option is better. Also, try to avoid using cell/cellfun/arrayfun whenever you can, vectors are way faster and even a plain for loop is more effecient

Do I always need to use a cell array to assign multiple values to a struct array?

I've got a nested struct array like
A(1).B(1).var1 = 1;
A(1).B(2).var1 = 2;
Now I want to change the values of var1 to using the elements of the vector x = [3; 4] for each of the respective values.
The result should be
A(1).B(1).var1 = 3;
A(1).B(2).var1 = 4;
I have tried
% Error : Scalar structure required for this assignment.
A(1).B.var1 = x;
% Error : Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
[A(1).B.var1] = x(:);
Curiously, if x is a cell array, the second syntax works
x = {3, 4};
[A(1).B.var1] = x{:};
Luckily, it's not too complicated to convert my numeric vector to a cell array using mat2cell, but is that the only way to do this assignment without a for loop?
What's the correct syntax for multiple assignment to a nested struct array? Can I use numeric vectors or do I have to use cell arrays?
The statement
[A(1).B.var1] = x{:};
is shorthand for
[A(1).B.var1] = deal(x{:});
(see the documentation for deal).
Thus you can also write
[A(1).B.var1] = deal(3,4);
I'm not aware of any other way to assign different values to a field in a struct array in a single command.
If your values are in a numeric array, you can easily convert it to a cell array using num2cell (which is simpler than the mat2cell you found).
data = [3,4];
tmp = num2cell(data);
[A(1).B.var1] = tmp{:};
In general, struct arrays are rather awkward to use for cases like this. If you can, I would recommend that you store your data in normal numeric arrays, which make it easier to manipulate many elements at the same time. If you insist on using a struct array (which is convenient for certain situations), simply use a for loop:
data = [3,4];
for ii = 1:length(A(1).B)
A(1).B(ii).var1 = data(ii);
end
The other alternative is to use table.

How to get multiple outputs of a function in a vector?

Say I have a function whose outputs are two reals a and b
[a,b]=function(c)
I'd like to get all the outputs in a vector v.
v=function(c) doesn't do what I want, v is 'a' only.
Of course here I could do v=[a,b].
But the function in question is ind2sub for a N-D array so it gives n outputs that I'd like to have in a vector directly.
Is there a way to do it?
Thanks very much!
You can use a cell array and a comma-separated list like so:
X = cell(N, 1);
[X{:}] = function(C);
The syntax X{:} is in fact expanded to [X{1}, X{2}, ...], which provides a valid sink for your function. As a result, each output variable will be stored in a different cell in X.
If each output variable is a scalar, you can flatten out the cell array into a vector by using yet another comma-separated list expansion:
v = [X{:}];

Is there a splat operator (or equivalent) in Matlab?

If I have an array (of unknown length until runtime), is there a way to call a function with each element of the array as a separate parameter?
Like so:
foo = #(varargin) sum(cell2mat(varargin));
bar = [3,4,5];
foo(*bar) == foo(3,4,5)
Context: I have a list of indices to an n-d array, Q. What I want is something like Q(a,b,:), but I only have [a,b]. Since I don't know n, I can't just hard-code the indexing.
There is no operator in MATLAB that will do that. However, if your indices (i.e. bar in your example) were stored in a cell array, then you could do this:
bar = {3,4,5}; %# Cell array instead of standard array
foo(bar{:}); %# Pass the contents of each cell as a separate argument
The {:} creates a comma-separated list from a cell array. That's probably the closest thing you can get to the "operator" form you have in your example, aside from overriding one of the existing operators (illustrated here and here) so that it generates a comma-separated list from a standard array, or creating your own class to store your indices and defining how the existing operators operate for it (neither option for the faint of heart!).
For your specific example of indexing an arbitrary N-D array, you could also compute a linear index from your subscripted indices using the sub2ind function (as detailed here and here), but you might end up doing more work than you would for my comma-separated list solution above. Another alternative is to compute the linear index yourself, which would sidestep converting to a cell array and use only matrix/vector operations. Here's an example:
% Precompute these somewhere:
scale = cumprod(size(Q)).'; %'
scale = [1; scale(1:end-1)];
shift = [0 ones(1, ndims(Q)-1)];
% Then compute a linear index like this:
indices = [3 4 5];
linearIndex = (indices-shift)*scale;
Q(linearIndex) % Equivalent to Q(3,4,5)

In MATLAB how can I set all the values of a matrix to string?

I have a MATLAB matrix, that is 1000x4, to use as an input for a function. I need to add a new column that contains a certain string. So how can I make a new column where all the values are 'TEST'?
Since it's a little unclear what you want, here are some options:
To make a 1000-by-4 matrix where each row is 'TEST', you can use the function REPMAT:
M = repmat('TEST',1000,1);
To add 'TEST' to the end of each row of a 1000-by-4 matrix of characters, you can use the function STRCAT:
M = repmat('a',1000,4); %# Sample matrix filled with 'a'
M = strcat(M,'TEST'); %# Append 'TEST' to each row of M
If your 1000-by-4 matrix is a numeric array instead of an array of characters, you will have to use cell arrays to combine the different types of data. Here's one way you can do this:
M = rand(1000,4); %# A matrix of random numeric values
M = num2cell(M,2); %# Put each row of M in a cell, making
%# a 1000-by-1 cell array
M(:,2) = {'TEST'}; %# Add a second column to the cell array,
%# where each cell contains 'TEST'
A matrix cannot contain a string (like 'TEST').
You need to use a cell array
If this is an existing matrix M of cell strings,
M(:,end+1) = {'TEST'};