Extract data from struct array

61 Ansichten (letzte 30 Tage)
Daniel Stein
Daniel Stein am 1 Jun. 2023
Bearbeitet: Stephen23 am 1 Jun. 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.

Antworten (1)

Stephen23
Stephen23 am 1 Jun. 2023
Bearbeitet: Stephen23 am 1 Jun. 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

Kategorien

Mehr zu Structures finden Sie in Help Center und File Exchange

Produkte


Version

R2019a

Community Treasure Hunt

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

Start Hunting!

Translated by