size of struct field from ncinfo - matlab

I want to get the size of a certain field inside a structure.
For example the size of the field Name inside the field Dimensions of the struct obtained from ncinfo:
finfo = ncinfo('example.nc');
finfo.Dimensions.Name
>>ans =
x
ans =
y
ans =
z
Just using size causes an obvious error:
size(finfo.Dimensions.Name)
Error using size
Too many input arguments.
How can I do it in an alternative way?
Also, I would like to save the content of finfo.Dimensions.Name in a separate array or struct. But I get a similar error. For example:
a.b=finfo.Dimensions.Name
returns the error:
Illegal right hand side in assignment. Too many elements.

Per the documentation for ncinfo, Dimensions is an array of structures, so you need to be more explicit with what you want to do.
If you want the size of the 'Dimensions' field then that is your query:
S.Dimensions(1).Name = 'x';
S.Dimensions(2).Name = 'y';
S.Dimensions(3).Name = 'z';
size(S.Dimensions)
Which returns:
ans =
1 3

Your problem is that the Dimensions field in the structure returned by ncinfo is itself an array of structures, and when you access a field of a structure array it returns a comma-separated list of values, one for each array element. You need to collect these values, for example in a cell array:
nameCell = {finfo.Dimensions.Name}; % Now a 1-by-3 cell array of names
If you just want to know the number of dimensions, you can check the size of the Dimensions field like so:
N = size(finfo.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.

extract the 4th filed of structure file in matlab

I have matlab data 1x617 stuct with 1 field and each row has 1x1 struct with 4 fields. How can I extract the data to get the 4th field for 617 data, the 4th field is nx1 double. Thanks
Depending on your variable structure, it can be sometimes easily solved by simply index reference it. However, in your case that you want to collect data from one specific field within array of struct variable, I would recommend to use structval on Matlab FileExchange
Here is the link:
Struct 2 array or cell for desiginated fieldname
Let's assume your variable looks like this
for idx = 1:617
b.a = ones(1,1)*idx;
b.b = ones(2,1)*idx;
b.c = ones(3,1)*idx;
b.d = ones(4,1)*idx;
s(1,idx).a = b;
end
The above code creates a 1x617 stuct with 1 field, and each row has 1x1 struct with 4 fields. And here I assume that the name of the 4th field in each row is the same.
Now use structval
r = structval(s,'d');
The result is a 1x617 cell array. If you happen to have same size for that field at each index (e.g. a nx1 array), then use
r = structval(s,'d','collapse',true);
to return a nx617 array

Convert cell array columns into matrix columns

I have a cell array (16x5) and I would like to extract all the values held in each column of the cell array and place them into a column within a matrix such that the columns are preserved (i.e. new matrix column for each cell array column).
What is the best way to do this?
I have tried:
for k=1:Samples
data(k,:) = [dist{:,k}];
end
But this returns the error
Subscripted assignment dimension mismatch.
However I am not sure why.
EDIT - Cell array structure:
Since your loop code is valid, I assume the error is being raised because data is preallocated with dimensions not matching the length of the comma-expanded dist column (Matlab will grow matrices with explicit indices but not with the : operator).
You just need to get the length of the data after the comma-separated expansion:
nElem = numel([dist{:,1}]);
Samples = size(dist,2);
data = zeros(Samples,nElem);
for k=1:Samples
data(k,:) = [dist{:,k}];
end
Or if you want it in columns
data = zeros(nElem,Samples);
for k=1:Samples
data(:,k) = [dist{:,k}]';
end

How to create an empty array in a matrix

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.