extract the 4th filed of structure file in matlab - 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

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

Copy array by indexing cell numbers

I am trying to extract specific columns from a "nested" array, the columns I need are nested, there are about a thousand columns, of which I only need the ones marked by index in another part of the array.
I have one Array{1,15} containing cells with numerical values (e.g. 2,5,10,53). These values are the index numbers i need to extract from another array.
indexnum = OutArray{1,15}(:);
Which arranges them in a column instead of a row, totally not necessary but seemed easier for me to progress with this.
Then I have the array containing the actual columns I want to extract/copy to a new array.
OutArray{1,14}{i,1}
So by the example numbers above, I need to copy column 2,5,10 and 53 to another array.
One of my more current attempts looks like this:
NewArray = []; %create new array
indexnum = OutArray{1,15}(:); %copy right index values to column
for i = indexnum{:} %use numeric value of every cell
NewArray = [NewArray, OutArray{1,14}{1,i}] %copy corresponding columns to NewArray
end
I also tried to use cell2mat(indexnum(1,:)), but that didn't help either.
To make clear the structure of the array:
OutArray{1,15} Contains cells with 1 value per column, which are index numbers for other array
OutArray{1,14} contains nested cells, 1 cell per column
OutArray{1,14}{1,x} contains columns with ~30 values per column, of which I want to copy the columns with the right indexes
For another array in which I just needed to copy all columns this code worked fine:
new1 = [];
for i = 1:length(OutArray{1,4})
new1 = [new1, OutArray{1,4}{i,1}]
end
It was a bit hard to understand because of so many cells into cells but your screenshots were very helpful. I will first highlight the errors and needed changes in your attemp:
NewArray = []; %create new array
indexnum = OutArray{1,15}(:); %copy right index values to column
for i = indexnum{:} %use numeric value of every cell
NewArray = [NewArray, OutArray{1,14}{1,i}] %copy corresponding columns to NewArray
end
Doing OutArray{1,15}(:) is exactly the same as OutArray{1,15} as you are just selecting the full cell of cells.
Your for loop uses indexnum{:} as the iterator but {:} returns a comma separated list and it does not work like (:) for arrays that give the full vector instead. In this case, when you assign indexnum{:} to a variable you get only the first element of the list. An example to ilustrate this:C = {1, 2, 3}; C{:} displays the full list, but x = C{:} only makes x = 1. To get all the elements you could group them in an array by doing: x = [C{:}].
So in your case you just need to add brackets to for i = [indexnum{:}] to get the iterator working.
To sum up, your code would be changed to:
NewArray = []; %create new array
indexnum = OutArray{1,15}; %copy right index values to column
for i = [indexnum{:}]
NewArray = [NewArray, OutArray{1,14}{1,i}}];
end
In addition, you could avoid the for loop and variables initialization with this single line code:
NewArray = [OutArray{1,14}{1,[OutArray{1,15}{1,:}]}];
As you can see, it just takes row 1 of your data OutArray{1,14} and the columns specified at each element of the indexes OutArray{1,15}. Brackets are needed twice because when indexing a cell with curly braces with more than one index at a time you always get a list and need to convert into an array as explained above.

size of struct field from ncinfo

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);

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 find mean of struct datatype in MATLAB?

I want to find the eccentricity of an image.
img = imread('47.jpg');
ecc=regionprops(img,'Eccentricity');
ecc =
255x1 struct array with fields:
Eccentricity
ecc(255)
ans =
Eccentricity: 0.2851
ecc(1)
ans =
Eccentricity: 0.4740
=========================
ecc is a variable of struct datatype. It will hold values of all the 255 objects. However, I want to find only one eccentricity and considering the mean of all these values.
Is there a way to find mean of struct value?
I tried for loop. calculating sum and dividing by total no. of objects. But MATLAB does not permit addition on struct data varible.
=======================================
img = imread('47.jpg');
ecc=regionprops(img,'Eccentricity');
numObj = numel(ecc);
sum=0;
index=1;
for k = 1: numObj
temp=ecc(index);
**sum=temp+sum;**
index=k+1;
end
imgEcc = sum/numObj;
**??? Undefined function or method 'plus' for input arguments of type 'struct'.**
===========================================
Please provide your inputs.
Scalar Data in Field
Within your loop, you must refer to the field name to access the data:
for k = 1: numObj
temp=ecc.Eccentricity(index);
sum=temp+sum;
index=k+1;
end
imgEcc = sum/numObj;
A more efficient method is to pull all of the eccentricities from the struct array using the fact that ecc.Eccentricity is itself a comma-separated list of values:
Eccentricities = [ecc.Eccentricity];
This is just like [ecc(1).Eccentricity, ecc(2).Eccentricity,...] by how Matlab handles struct arrays.
Since the eccentricities are now in a double array, you can use mean:
EccentricityBar = mean(Eccentricities);
Array Data in Field
If the data in the struct array is not scalar, the semantics of the value extraction depend on the shape of data in the field.
Regardless of whether the field data is a row vector (1xN), a column vector (Nx1), or a matrix (MxN), the matrix formed by wrapping the field reference in square braces is always made from comma-separated concatenation.
In other words, if we have a struct array foo with field bar, the following two lines are equivalent:
baz1 = [foo(1:3).bar];
baz2 = [foo(1).bar,foo(2).bar,foo(3).bar];
To access certain elements of the baz array requires knowing the shape of the data in foo(k).bar.
If the data was a row vector of length N, the original columns from the struct array can be extracted using subscripts and the the stride N:
col1 = baz(1:N:end);
col2 = baz(2:N:end);
...
col# = baz(#:N:end);
If the data was a column vector of length N, the original rows from the struct array are the rows of baz:
row1 = baz(1,:);
row2 = baz(2,:);
...
row# = baz(#,:);
And for matrix data, combinations of the above two methods are where to look.
For example, if you had a struct array data with the field Centroid that had the x and y centroid locations in a 1x2 array, we could extract the values like
centroids = [data.Centroid];
xbar = centroids(1:2:end);
ybar = centroids(2:2:end);
whereas, if the centroid locations were a 2x1 array, we would extract like
centroids = [data.Centroid];
xbar = centroids(1,:);
ybar = centroids(2,:);