Extract data from struct array
34 ビュー (過去 30 日間)
古いコメントを表示
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 件のコメント
回答 (1 件)
Stephen23
2023 年 6 月 1 日
編集済み: Stephen23
2023 年 6 月 1 日
"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 件のコメント
参考
カテゴリ
Help Center および File Exchange で Structures についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!