Extract data from struct array
34 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
I have a struct array that each element contains substructures with data that I would like to extract into a numeric array or timeseries. The data structure is set up similar to the example I created below:
dt = 1/1000;
T = 5;
t = 0:dt:T;
data = struct([]);
for it = 1:length(t)
data(it).t = t(it);
data(it).sys = genStruct(t(it));
end
function sOut = genStruct(t)
sOut = struct;
sOut.sys1 = struct;
sOut.sys2 = struct;
sOut.sys1.sub1 = genSubsystemStruct(t);
sOut.sys1.sub2 = genSubsystemStruct(t);
sOut.sys2.sub1 = genSubsystemStruct(t);
sOut.sys2.sub2 = genSubsystemStruct(t);
end
function sOut = genSubsystemStruct(t)
sOut = struct;
sOut.t = t;
sOut.dataPoint1 = randn();
sOut.dataPoint2 = randn();
end
Since data(1:10).sys.sys1.sub1.dataPoint1 does not work, the only method I have found to get an array from this structure is to create a structure map and loop over struct as shown below:
sFieldsOfInterest = struct; % Data map
sFieldsOfInterest.data = ["t"]; % Fields listed under data are saved to a row
sFieldsOfInterest.sys = struct;
sFieldsOfInterest.sys.sys1 = struct('sub1', struct('data', ["dataPoint1", "dataPoint2"]), ...
'sub2', struct('data', ["dataPoint1", "dataPoint2"]));
sFieldsOfInterest.sys.sys2 = struct('sub1', struct('data', ["dataPoint1", "dataPoint2"]), ...
'sub2', struct('data', ["dataPoint1", "dataPoint2"]));
dataArray = [];
for ii = 1:length(data)
dataArray(end+1,:) = getDataFromStructArray(data(ii), sFieldsOfInterest);
end
function row = getDataFromStructArray(dataStruct, structure)
row = [];
f = fields(structure);
for ii = 1:length(f)
if f{ii} == "data"
fois = structure.(f{ii}); % Fields of interest
for foi = fois
row = [row dataStruct.(foi)];
end
else
row = [row getDataFromStructArray(dataStruct.(f{ii}), structure.(f{ii}))];
end
end
end
Is there a better way to access this data? For the most part, the data fields of interest are not multi-dimensional arrays.
0 commentaires
Réponses (1)
Stephen23
le 1 Juin 2023
Modifié(e) : Stephen23
le 1 Juin 2023
"Since data(1:10).sys.sys1.sub1.dataPoint1 does not work.."
First lets generate your sample structure:
dt = 1/1000;
T = 5;
t = 0:dt:T;
data = struct([]);
for it = 1:length(t)
data(it).t = t(it);
data(it).sys = genStruct(t(it));
end
Because all of your nested structures are scalar you can simply use ARRAYFUN:
F = @(s)s.sys.sys1.sub1.dataPoint1;
V = arrayfun(F, data)
Or you could use a few comma-separated lists:
s1 = [data.sys];
s2 = [s1.sys1];
s3 = [s2.sub1];
V = [s3.dataPoint1]
"For the most part, the data fields of interest are not multi-dimensional arrays."
What sizes do you expect the output to be? How do you want them concatenated together?
If using comma-separated lists then you will need to carefully consider using e.g. VERTCAT, HORZCAT, a cell array, ...
You may also find dynamic fieldnames useful:
If you want complete flexibility (only gets one field value, but allows any number of nested sturctures, can define all levels and indexing via a cell array i.e. comma-separated list):
function sOut = genStruct(t)
sOut = struct;
sOut.sys1 = struct;
sOut.sys2 = struct;
sOut.sys1.sub1 = genSubsystemStruct(t);
sOut.sys1.sub2 = genSubsystemStruct(t);
sOut.sys2.sub1 = genSubsystemStruct(t);
sOut.sys2.sub2 = genSubsystemStruct(t);
end
function sOut = genSubsystemStruct(t)
sOut = struct;
sOut.t = t;
sOut.dataPoint1 = randn();
sOut.dataPoint2 = randn();
end
0 commentaires
Voir également
Catégories
En savoir plus sur Structures dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!