How process many structured arrays at once

7 views (last 30 days)
I want to plot/process some test data, but it was stored in structured arrays with unhelpful / sequential names (Signal_000, Signal_001 ...Signal_157). I would like to sequentially extract the character array, make it a string, turn it into a variable name, and then assign the data in that structured array.
All the posts I've seen say don't do this (was considering eval). How should I go about doing this?
  3 Comments
RichardB
RichardB on 30 Aug 2018
Really, I'm not looking to write very efficient code. I just need a way to take a 100 odd struct files and turn them into 100 simple arrays (row) with a useful name I can recognize.
jonas
jonas on 30 Aug 2018
Edited: jonas on 30 Aug 2018
And you received several methods to solve your problem. If you are unable to solve it by now, then you should consider uploading a sample data set and be thankful that people are willing to help.
I'm guessing most people here (at least myself) get some satisfaction from helping people improve their coding. Solving a trivial problem by writing buggy code is not something I will spend my evening doing.

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 31 Aug 2018
Edited: Stephen23 on 31 Aug 2018
"I want to plot/process some test data, but it was stored in structured arrays with unhelpful / sequential names (Signal_000, Signal_001 ...Signal_157). I would like to sequentially extract the character array, make it a string, turn it into a variable name, and then assign the data in that structured array."
So far the actual data files have not been described very well: I am going to assume that names of the .mat files corresponds exactly to the names of the structures, that each file/structure has a different name, and that each file contains one structure only. This can be processed very easily, something like this:
D = 'path of the folder where the data files are';
S = dir(fullfile('*.mat'));
C = cell(1,numel(S));
for k = 1:numel(S)
T = load(fullfile(D,S(k).name));
C(k) = struct2cell(T);
C(k).filename = S(k).name;
end
You now have all of the data in one cell array C, which is trivial to process in a loop. For example, your example data for file 0045 would then be
Z{46}.y_values.quantity.g
Z{46}.function_record.name
and the filename is always available:
Z{46}.filename
If all of the structures contain the same fields, then you can easily convert this cell array into one non-scalar structure like this:
Z = [C{:}]
Your example data for file 0045 would then be
Z(46).y_values.quantity.g
Z(46).function_record.name
etc
and you can do neat things, like get all of filenames in one cell array:
{Z.filename}
  7 Comments
Stephen23
Stephen23 on 31 Aug 2018
Edited: Stephen23 on 31 Aug 2018
@RichardB: using struct2cell is a very good idea, together with fieldnames. Something like this works on your sample file (and a simple copy I made):
D = '.'; % directory where the files are:
S = dir(fullfile(D,'*.mat'));
C = cell(1,numel(S));
for k = 1:numel(S)
T = load(fullfile(D,S(k).name));
F = fieldnames(T);
T = struct2cell(T);
T = vertcat(T{:});
[T.fieldname] = F{:};
[T.filedata] = deal(S(k));
C{k} = T;
end
Z = vertcat(C{:});
It returns one structure Z which contains all of the file data, the filenames, and the fieldnames. So you can process these however you want. The output is easy to access, e.g. the second element of the structure contains the data from :
>> Z(2).filedata.name
ans =
SampleRun1.mat
>> Z(2).fieldname
ans =
Signal_005
>> Z(2).x_values
ans =
start_value: 7.66712283871882e-05
increment: 9.765625e-05
number_of_values: 4122210
quantity: [1x1 struct]
>> Z(2).x_values.increment
ans =
9.765625e-05
>> Z(2).number_of_values
ans =
4122210
You can easily extend this to work over multiple directories. You can add bells and whistles yourself, such as sorting based on the original fieldnames, etc. The test files are attached.
RichardB
RichardB on 31 Aug 2018
Thanks much. I think that will get me where I want to go.

Sign in to comment.

More Answers (3)

jonas
jonas on 30 Aug 2018
Edited: jonas on 30 Aug 2018
As you've already read, do not. You already have your data in a struct, which is much more convenient than indexed variables. You can use dynamic field names to call your data from the struct. It's one of the common options for avoiding the infamous eval function.
Basic syntax is:
F='Signal_000'
out=MyStruct.(F)
It may however be even more convenient to put your data in a cell array, in which case you can use struct2cell

RichardB
RichardB on 30 Aug 2018
I got this data from a 3rd party, so I do not have any control over that. I need to figure out which Signal_??? has acceleration data for turbo 1 in the Z axis (found somewhere in the struct Signal_???). Maybe if I could simply find a way to sequentially rename the struct array so I can determine which one I want to investigate) so I don't have to interrogate each one individually.
  1 Comment
jonas
jonas on 30 Aug 2018
Edited: jonas on 30 Aug 2018
I mean, you already received several solutions for how to process your data. However, the actual structure of the data remains a bit ambiguous so it's difficult to give you more specific, detailed, solutions. If you tell us exactly what you want to do and upload the data, then we can give you some actual useable code.
It's difficult for us, who have no knowledge of your background, to understand what "acceleration data for turbo 1 in the Z axis" actually means and how to help you find it.

Sign in to comment.


RichardB
RichardB on 30 Aug 2018
Thanks for the information from everyone...internet is amazing. I read some of the stuff about not using eval, but it remains the only way I see to do what I want. No doubt I am not understanding something here...and I need to read a lot of stuff.
I attached what the data structure looks like. For example, I want to plot time vs a particular acceleration, but I have no idea which struc it is in. Maybe there was a different way to bring it in from the *.mat file.
I am not processing the data, per se. I am trying to interrogate it.
I want to determine which name goes with which signal belongs to the data I want. The name of the data (which is everything to me) is found in: Signal_???.function_record.name The data is in Signal_???.y_values.values
  3 Comments
RichardB
RichardB on 30 Aug 2018
Sorry this is dragging on and I am not clear.
Do you want to structure the data in a more convenient way, so that you can access it more easily by name of the series the corresponding data? Yes
I may plot all the data, but generally that is unhelpful. It depends on what I find. Maybe figuring out how to load the *.mat file and search for the data I want would help, but I don't understand how that would work given how it is structured.
How will I use the date? I will plot acceleration vs time (find the worst ones), acceleration vs rpm, create a Campbell plot, FFT, compare 4 vertical accelerations to see if it is pitching, rolling, translating, or twisting, check transmissibility to see which structure is exciting the one that has a problem. I can double integrate and AC couple the acceleration data to get "stationary" displacement. But I don't want to do this to everything.
Stephen23
Stephen23 on 31 Aug 2018
Edited: Stephen23 on 31 Aug 2018
"Really, I'm not looking to write very efficient code. I just need a way to take a 100 odd struct files and turn them into 100 simple arrays (row) with a useful name I can recognize."
Whether you are just investigating your data or trying to write an efficient tool for processing lots of files, it does not change the fact that magically accessing variable names is a bad idea. Data imported using magically named variables cannot be accessed easily in a loop, which is why it forces you to continue to use slow and complex method to access your data. In contrast, when you import your data using better methods, then accessing it is simpler, and there are lots of neat tools that work on whole arrays that help you to process your data, which only work on an array and not on lots of separate variables.
The upshot is, this is not just about making more efficient code, as you simply dismissed earlier, but also about making accessing your data easier, and means you can use lots of tools that will help you to analyze your data.
" Maybe figuring out how to load the *.mat file and search for the data I want would help, but I don't understand how that would work given how it is structured."
It would help. To start with, you need to load the files into output variables:
S = load(...)
What to do next depends on exactly what the .mat files contain. It would help us a lot, if you accurately described how you get the data, in particular:
  • is the data stored in one .mat file, or lots of them?
  • how many variables are stored in each .mat file?

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!