MATLAB: Not just another dynamic variable naming question! Generating a new string and using it in a command.

dataevalimportMATLABvariables

I am working on a large data project that has potentially thousands of similarly named files in CSV format that I need to analyze in matlab. These files are named nnnwavex.csv (where nnn = a number and x = either I II III or V).
Ex Directory Contents
  • 352waveI.csv
  • 352waveII.csv
  • 352waveIII.csv
  • 352waveV.csv
My previous code to import this was to enter the following
wave352i = importdata('352waveI.csv');
tele352i = wave352i.data;
text352i = wave352i.textdata;
wave352ii = importdata('352waveII.csv');
tele352ii = wave352ii.data;
text352ii = wave352ii.textdata;
wave352iii = importdata('352waveIII.csv');
tele352iii = wave352iii.data;
text352iii = wave352iii.textdata;
wave352v = importdata('352waveV.csv');
tele352v = wave352v.data;
text352v = wave352v.textdata;
Now I have generated a bit of variable naming code that seems to work well for the first part (importing the file as a struct of data and textdata). I have spent hours reading the material about why variable naming is not ideal. This is simply to import large numbers of files quickly.
x=352;
y='wave';
z='I'
a='.csv'
b='tele'
c='.data'
cat(2,num2str(x),y,z,a)
eval(['temp = importdata(ans)']);
cat(2,y,int2str(x),z);
v = genvarname(ans);
eval([v '= temp']);
z='II'
cat(2,num2str(x),y,z,a)
eval(['temp = importdata(ans)']);
cat(2,y,int2str(x),z);
v = genvarname(ans);
eval([v '= temp']);
z='III'
cat(2,num2str(x),y,z,a)
eval(['temp = importdata(ans)']);
cat(2,y,int2str(x),z);
v = genvarname(ans);
eval([v '= temp']);
z='V'
cat(2,num2str(x),y,z,a)
eval(['temp = importdata(ans)']);
cat(2,y,int2str(x),z);
v = genvarname(ans);
eval([v '= temp']);
clear x y z v temp c b ans a
This leaves me with four struct files
  • wave352I
  • wave352II
  • wave352III
  • wave352V
how can I make a script that can then build a variable name that accomplishes the following & gives me a double and a cell from the original struct?
If I create a string a = 'wave352V.data', I cannot use it in my code to call that subset of the struct and apply it to a new variable.
tele352v = wave352v.data;
text352v = wave352v.textdata;
I could use excel and word and build a script that uses mail merge to create multiple iterations of the initial code I demonstrated above, but that seems like a very amateur way to approach this.
Any ideas would be appreciated!

Best Answer

"Each ### is a patient and each of the roman numerals is a separate ECG channel. Each of the leads has hundreds of rows of data that need to have several pre-processing and filtering steps applied to them. There are a few steps that do calculation on all signals at once (ie the same row on all four channels)."
Well, now we're finally beginning to get somewhere...still much to be clarified, but this at least gives a place from which to start.
First of all, it is trivial as Stephen has pointed out to open a file for any given patient number; simply
pn=input('Which patient, please? ','s');
srchstr=sprintf('%s*',pn); % build root search pattern
d=dir([srchstr '.csv']); % and search for those .csv
will return the list of all .csv files for the patient which you can then process sequentially by iterating over the directory structure, d.
If you need a given channel, add that to the wildcard pattern; you're fortunate in having created (or someone did for you) a pretty usable naming convention here.
chnls={'I','II','III','IV'}; % the list from which to choose
[ich,ok]=listdlg('PromptString','Select Channel', ...
'SelectionMode','single', ...
'ListString',chnls);
if ok
srchstr=strcat(srchstr,chnls(ich)); % add chnl suffix
end
d=dir([srchstr '.csv']);
also illustrating another user interactive tool that may make usage simpler for you.
Given your description of the file structure, one very likely way you might approach it would be, as Steven suggested, the table. As a trivial example, I built a sample record...
ts=cellstr(datestr(now)); % a timestamp
chnl={'C001'}; % channel/ASCII?? code however is
ecg=randn(1,480); % and the 480x data vector associated @t
t=table(datetime(ts), ...
categorical(chnl), ...
ecg, ...
'VariableNames',{'Time','Chnl','ECG'})
t =
Time Chnl ECG
____________________ ____ ______________
06-May-2017 09:25:24 C001 [1x480 double]
and VOILA! you've got a database. Patient ID can be incorporated, too, of course, as well as any other corollary info required. Then grouping variables can be used to select desired characteristics from the table by patient, time, whatever...
What we still don't know now is how much of these data are to be processed concurrently, but there surely are very powerful ways to organize the data to do whatever it is that is required without needing named variables(*) to do so.
The above is just one of many alternatives; which would work best will depend on the remaining details of what actually is to be done with the data as far as the agglomeration of what is needed in a single data structure at any one time.
(*) NB: A "named variable" is NOT in any way, shape or form the same as using a variably-named structure fieldname or as the variable name in a table. The former is essentially impossible to deal with in a generic fashion with any code of any complexity whatever; the latter are, essentially, trivial to use in Matlab.