MATLAB: How to tabulate structs with same fields - arrays

I have use a 428×1 cell array called data
data = {[1×1 struct]
[1×1 struct]
....
[1x1 struct]}
These struct all have the same structure
data {2,1}
>>struct with fields
additional_model_information: 'H Series,S3150-S0-AW-04-02-C-F421,'
ceiling_fan_size_diameters_in_inches: '60'
airflow_efficiency_cfm_watt_low: '727'
airflow_efficiency_cfm_watt_high: '392'
The structure fields are the same for all 428 cells, and the fields values change in each struct.
How could i create a table that puts all of the structs together so that it shows all of the field values for each field? Pehaps using a nested for loop?
I eventually want to export this data to excel.

Let's say you've got your nx1 cell array of structs, data. This method doesn't assume you have 4 fields in your data or any knowledge of what they are called. You could even use it with structs with different fieldnames if you included some try/catch logic.
You can get the field names of a representative struct using fieldnames
fnames = fieldnames(data{1});
Then set up some output cell array out of the correct size
out = cell(numel(fnames), numel(data));
Then use nested loops to 1. loop through items in data and 2. loop through field names.
for n = 1:numel(data)
for field = 1:numel(fnames)
temp = data{n};
out{field, n} = temp.(fnames{field});
end
end
Finally, append the field names as the first column
out = [fnames, out];
And write the cell array to your Excel file
% File location, cell array, sheet, cell
xlswrite('C:\...\test.xlsx', out, 1, 'A1');

How about
T = cell(length(data) , 4);
for k = 1 : length(data)
T(k , :) = {data{k}.additional_model_information , ...
data{k}.ceiling_fan_size_diameters_in_inches, ...
data{k}.airflow_efficiency_cfm_watt_low, ...
data{k}.airflow_efficiency_cfm_watt_high};
end
Then you can use xlswrite to export to excel.

Related

Exporting a cell structure from Matlab to Excel

I have a cell structure which has <1*40 struct> inside it. Every structure has the same field names (each having 12 field names and respective values). I want to Export this cell Array into an Excel file such that all the field names become the heading (12 consecutive columns), and below each field Name Comes its respective field values.
I have tried xlswrite by using cell2struct but it does not help.
If anyone could help me with this ?
If your input data looks something like this:
data = {struct('a', 1, 'b', 2), struct('a', 3, 'b', 4)};
You can process it using a combination of struct2cell and simple concatenation.
First convert from a cell array to an array of structs:
data = cat(2, data{:});
Then you can get the values using struct2cell
values = struct2cell(data(:));
Then the column names should simply be the fieldnames of your struct
headers = fieldnames(data);
Then you can concatenate the headers with the data to yield the input to xlswrite
xlsdata = cat(2, headers, values)'
xlswrite('filename.xlsx', xlsdata);
xlsdata =
'a' 'b'
[1] [2]
[3] [4]
We can condense this a little bit:
xlsdata = cat(2, fieldnames(data{1}), struct2cell(cat(2, data{:})))';
xlswrite('filename.xlsx', xlsdata);

How to name variables in a data array using a for loop

I have an array within an array and I am trying to name the variables using a for loop as there are a lot of variables. When I use the following simple code Time1 = dataCOMB{1,1}{1,1}(1:1024, 1); it opens the first cell in an array and proceeds to open the first cell in the following array and finally defines all the values in column 1 rows 1 to 1024 as Time1. However I have 38 of these different sets of data and when I apply the following code:
for t = 1:38
for aa = 1:38
Time(t) = dataCOMB{1,1}{1,aa}(1:1024, 1);
end
end
I get an error
In an assignment A(I) = B, the number of elements in B and I must be the same.
Error in Load_Files_working (line 39)
Time(t) = dataCOMB{1,1}{1,aa}(1:1024, 1);
Basically I am trying to get matlab to call the first column in each data set Time1, Time2, etc.
The problem:
1)You'd want to extract in a cell row...
2) ...the first 1024 numbers in the 1st column...
3) ...from each of the first 38 cells of a cell array.
The plan:
1) If one wants to get info from each element of a cell array (that is, an array accessed via {} indexing), one may use cellfun. Calling cellfun(some_function, a_cell_array) will aggregate the results of some_function(a_cell_array{k}) for all possible k subscripts. If the results are heterogeneous (i.e. not having the same type and size), one may use the cell_fun(..., 'UniformOutput', false) option to put them in an output cell array (cell arrays are good at grouping together heterogeneous data).
2) To extract the first 1024 numbers from the first column of an numeric array x one may use this anonymous function: #(x) x(1:1024,1). The x argument will com from each element of a cell array, and our anonymous function will play the role of some_function in the step above.
3) Now we need to specify a_cell_array, i.e. the cell array that contains the first 38 cells of the target. That would be, simply dataCOMB{1,1}(1,1:38).
The solution:
This one-liner implements the plan:
Time = cellfun(#(x) x(1:1024,1), dataCOMB{1,1}(1,1:38), 'UniformOutput', false);
Then you can access your data as in this example:
this_time = Time{3};
Your error is with Time(t). That's not how you create a new variable in matlab. To do exactly what you want (ie, create variables names Time1, Time2, etc...you'll need to use the eval function:
for aa = 1:38
eval(['Time' num2str(aa) '= dataCOMB{1,1}{1,aa}(1:1024,1);']);
end
Many people do not like recommending the eval function. Others wouldn't recommend moving all of your data out of a data structure and into their own independently-named variables. So, to address these two criticisms, a better alternative might be to pull your data out of your complicated data structure and to put it into a simpler array:
Time_Array = zeros(1024,38);
for aa = 1:38
Time_Array(:,aa) = dataCOMB{1,1}{1,aa}(1:1024,1);
end
Or, if you don't like that because you really like the names Time1, Time2, etc, you could create them as fields to a data structure:
Time_Data = [];
for aa = 1:38
fieldname = ['Time' num2str(aa)];
Time_Data.(fieldname) = dataCOMB{1,1}{1,aa}(1:1024,1);
end
And, in response to a comment below by the original post, this method can be extended to further unpack the data:
Time_Data = [];
count = 0;
for z = 1:2;
for aa = 1:38
count = count+1;
fieldname = ['Time' num2str(count)];
Time_Data.(fieldname) = dataCOMB{1,z}{1,aa}(1:1024,1);
end
end

Struct array initialization without values

I have a structure
AStructX : 7x1 struct array with fields:
field1
field2
field3
field4
field5
Now I want to generate an empty 1x7 that looks like the previous struct, but with empty values.
I tried
AStructY = repmat(AStructX(1),1,7); but the values of AStructX is copied.
I tried
AStructY = repmat(AStructX(1),1,0); when I add values to it, it pass with MATLAB, but Coder generation fails with the following error message
??? Subscripting into an empty matrix is not supported.
Use cell2struct:
len = 7;
fn = fieldnames(AStructX)
AStructY = cell2struct(repmat({[]},numel(fn),len),fn)
That gives a 7x1 struct array with the same fields, empty contents. If you want a 1x7, simply transpose the array (i.e. AStructY = cell2struct(...).').
I'll make the following assumptions:
1. AStructX is 2-D.
2. You want the new structure to have the size size(AStructX').
3. The field names are not fixed.
To do this, you first need the fieldnames, then create a new struct with empty cells as values:
names = fieldnames(AStructX)'; %'// row vector
len = length(names); %// number of fields
for i=1:len
names{2,i} = cell(size(AStructX')); %'// the contents are empty
end
AStructY = struct( names{:} ); %// will take the names matrix columnwise
This will result in completely empty entries ([]), if you want to initialize the values to 0 instead, the line inside the loop becomes
names{2,i} = num2cell(zeros(size(AStructX'))); %'// initialize values to 0

Read multiple values from array dynamically in MATLAB

I have an array of structures.
I'm trying to select several records from the array, that match some condition.
I know there's this option: (For example array A with field f1):
A([A.f1]==5)
Which would return all the records that have f1 = 5.
But I want to do it for several different fields, in a loop. I saved the fields names in a cell array, but I don't know how to do the same with a dynamic field name.
I know there's the 'getfield' function, but it only selects a field from a single structure.
Is there a way to do it?
Thanks!
To access dynamically a field of a structure:
% Create example structure
s.a = 1;
s.b = 2;
% Suppose you retrieve the fieldnames (or hardcode them fnames = {'a','b'})
fnames = fieldnames(s);
The you can retrieve e.g. the second one:
s.(fnames{2})
In a loop
for f = 1:numel(fnames)
s.(fnames{f})
end
In your case:
A([A.(fnames{ii})] == n)
This code will run through the first 5 records of your dynamical names
for i=1:5
eval(['A([A.' cell_array{i} ']==5)'])
end

cell array of strings to matlab structure

I need to create a matlab structure as such ds=struct('name',{{'my_name_is'},{'matlab_thining_hair'}}) which stores as a 1x2 struct array with fields: name. A call to ds.name generates the output:
ds.name
ans =
'my_name_is'
ans =
'matlab_thining_hair'
Please note the single quotes in the output. They are important. That said, I need to create the above mentioned structure using the following variable:
X = [1x46 char] [1x47 char] i.e., 1x2 cell, which I believe is actually a cell array of strings. Among other things, I've tried the following:
Y = cell2struct(X, 'name', 1)'
which results in a 1x2 structure array with fields name, however a call to Y generates the output:
Y.name
ans = my_name_is
ans = matlab_thining_hair
Note that the single quotes in the output are missing, and albeit both Y and ds are 1x2 struct arrays with fields name, the field values are not formatted the same and the structures also vary in their bytes size. How to format the field values as character arrays?
In your first case you have created a struct with two fields whose values are cell arrays. The cell arrays are displayed with quotes.
In your second case your struct fields have char arrays which is what you want. Char arrays display without quotes.
You can verify this by typing in your command prompt {'abc'} and then 'abc'.
In your first case you can create non-cell array field values by passing the strings outside cell parenthesis.
ds=struct('name',{'my_name_is','matlab_thining_hair'})
Stick your char strings in another layer of cells before calling cell2struct. Instead of:
X = { 'foo', 'bar' }
Try:
X = { {'foo'}, {'bar'} }
That is, a 1-by-2 cell whose cell contents are themselves cells, not chars. Then cell2struct(X, 'name', 1) should give you a struct array with fields of cell arrays.
If your existing X is a cellstr, I think you can just call num2cell on it to push each cell down into another layer of cell indirection.

Resources