Extract data from struct array

34 visualizzazioni (ultimi 30 giorni)
Daniel Stein
Daniel Stein il 1 Giu 2023
Modificato: Stephen23 il 1 Giu 2023
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.

Risposte (1)

Stephen23
Stephen23 il 1 Giu 2023
Modificato: Stephen23 il 1 Giu 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)
V = 1×5001
-1.1297 0.6164 -0.6211 0.3362 0.0718 -0.4912 -0.1255 1.1036 -0.2441 -1.3993 -0.2652 0.0855 1.3243 -1.7874 -0.4221 -1.1474 0.4290 0.0323 -0.1947 -0.4415 0.4525 0.4684 0.4993 -0.3849 -0.7085 0.5279 2.2160 -0.6229 1.3110 -0.6714
Or you could use a few comma-separated lists:
s1 = [data.sys];
s2 = [s1.sys1];
s3 = [s2.sub1];
V = [s3.dataPoint1]
V = 1×5001
-1.1297 0.6164 -0.6211 0.3362 0.0718 -0.4912 -0.1255 1.1036 -0.2441 -1.3993 -0.2652 0.0855 1.3243 -1.7874 -0.4221 -1.1474 0.4290 0.0323 -0.1947 -0.4415 0.4525 0.4684 0.4993 -0.3849 -0.7085 0.5279 2.2160 -0.6229 1.3110 -0.6714
"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

Categorie

Scopri di più su Structures in Help Center e File Exchange

Prodotti


Release

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by