Matlab: dynamic name for structure - matlab

I want to create a structure with a variable name in a matlab script. The idea is to extract a part of an input string filled by the user and to create a structure with this name. For example:
CompleteCaseName = input('s');
USER WRITES '2013-06-12_test001_blabla';
CompleteCaseName = '2013-06-12_test001_blabla'
casename(12:18) = struct('x','y','z');
In this example, casename(12:18) gives me the result test001.
I would like to do this to allow me to compare easily two cases by importing the results of each case successively. So I could write, for instance :
plot(test001.x,test001.y,test002.x,test002.y);
The problem is that the line casename(12:18) = struct('x','y','z'); is invalid for Matlab because it makes me change a string to a struct. All the examples I find with struct are based on a definition like
S = struct('x','y','z');
And I can't find a way to make a dynamical name for S based on a string.
I hope someone understood what I write :) I checked on the FAQ and with Google but I wasn't able to find the same problem.

Use a structure with a dynamic field name.
For example,
mydata.(casename(12:18)) = struct;
will give you a struct mydata with a field test001.
You can then later add your x, y, z fields to this.
You can use the fields later either by mydata.test001.x, or by mydata.(casename(12:18)).x.
If at all possible, try to stay away from using eval, as another answer suggests. It makes things very difficult to debug, and the example given there, which directly evals user input:
eval('%s = struct(''x'',''y'',''z'');',casename(12:18));
is even a security risk - what happens if the user types in a string where the selected characters are system(''rm -r /''); a? Something bad, that's what.

As I already commented, the best case scenario is when all your x and y vectors have same length. In this case you can store all data from the different files into 2 matrices and call plot(x,y) to plot each column as a series.
Alternatively, you can use a cell array such that:
c = cell(2,nufiles);
for ii = 1:numfiles
c{1,ii} = import x data from file ii
c{2,ii} = import y data from file ii
end
plot(c{:})
A structure, on the other hand
s.('test001').x = ...
s.('test001').y = ...

Use eval:
eval(sprintf('%s = struct(''x'',''y'',''z'');',casename(12:18)));
Edit: apologies, forgot the sprintf.

Related

"Dot indexing is not supported for variables of this type" for a code that was running perfectly fine?

I have some MATLAB code that I worked on with someone who is much more experienced in MATLAB than I am. The code was running perfectly fine the other day. When I tried running it today, I got the error "Dot indexing is not supported for variables of this type" and I have tried reading through many other stack overflow questions on the topic, but still struggling to resolve my issue. I will include the code up until the error below. Based on what I've read, it might be something to do with structure? I would appreciate any help or tips you could send my way. Thank you!
for j = 3:length(files)
files(j).name
folder_name = files(j).folder;
file2load = strcat(folder_name, '\', files(j).name);
data_input = load(file2load);
trace_names = fieldnames(data_input);
for i = 1:length(trace_names)
data_to_plot.x = data_input.(char(trace_names(i))).data.x;
data_to_plot.y = data_input.(char(trace_names(i))).data.y;
As the comments point out, it is not clear why you are getting this error, but I can tell you what is causing it. 'Dot indexing' is a way of accessing data fields in a type of Matlab variable called a struct. In your snippet files(j) is not a struct.
For example, you cannot do this:
>> s = {}; % s is a cell array (not a struct)
>> g = {};
>> g{1} = 'lala';
>> s{1} = g;
>> s.g % cannot access g using this syntax
Dot indexing is not supported for variables of this type.
But if you make s a struct, you can:
>> s = struct
s =
struct with no fields.
>> s.item1 = g; % create a field called item1 to hold the stuff in g
>> s.item1 % now you can use dot indexing to access the stuff you put in there
ans =
1×1 cell array
{'lala'}
I would guess that this snippet is part of a function where files is an argument or down the line of a script in which files is earlier defined. Probably the other day with your colleague, you had files set to a variable that is indeed an array of structures with the items name etc inside of them. Since then, something changed the value of files to an array of non-struct types.

Sequential import of datafiles according to rule in Matlab

I have a list of .txt datafiles to import. Suppose they are called like that
file100data.txt file101data.txt ... file109data.txt I want to import them all using readtable.
I tried using the for to specify a vector a = [0:9] through which matlab could loop the readtable command but I cannot make it work.
for a = [0:9]
T_a_ = readtable('file10_a_data.txt')
end
I know I cannot just put _a_ where I want the vector to loop through, so my question is how can I actually do it?
Thank you in advance!
Here is a solution that should work even if you have missing files in your folder (e.g. you have file100data.txt to file107data.txt, but you are missing file file108data.txt and file109data.txt):
files=dir('file10*data.txt'); %list all data files in your folder
nof=size(files,1); %number of files
for i=1:nof %loop over the number of files
table_index=files(i).name(7) %recover table index from data filename
eval(sprintf('T%s = readtable(files(i).name)', table_index)); %read table
end
Now, please note that is it generally regarded as poor practice to dynamically name variables in Matlab (see this post for example). You may want to resort to structures or cells to store your data.
You need to convert the value of a into a string and combine strings together, like this:
Tables = struct();
for a = 0:9
% note: using dynamic structure field names to store the imported tables
fname = ['file10_' num2str(a) '_data'];
Tables.(fname) = readtable([fname '.txt']);
end

Matlab: how to rename a sub-field

Let me describe the question in this way. I have a .mat file, and if I open it, it contains a 1x10 struct data. In each data, it has a 1x5 struct (or field) called res. In res, it has a 1x1 struct (or field) called, let's say, foo. Thus, I have ixj copies of data(i).res(j).foo .
Is there anyway I can change the name of this foo? say I want all data(i).res(j).foo to become data(i).res(j).bar
I did search on the internet, and tried a few ways (add field and delete, create a temp field, use cell2field or fieldtofile, etc.) and all of them didn't work. The most frequent returned error is "Subscripted Assignment between dissimilar structures."
Please help, thanks in advance!
The safest way is probably by looping over data twice, the first pass creating a new field bar for each subfield like data(i).res(j).bar=data(i).res(j).foo, then the second pass deletes the old fields like data(i).res(j) = rmfield(data(i).res(j),'foo').
Thanks caoy and NotLikeThat. I finally came to an conclusion.
data2 = data
for i=1:10
for j = 1:5
data(i).res(j).bar = data2(i).res(j).foo;
end
data(i).res = rmfield(data(i).res, 'foo');
end
I probably need to removed i, j, and data2 after running this script.

Matlab: Understanding a piece of code

I have a matlab code which is for printing a cell array to excel. The size of matrix is 50x13.
The row 1 is the column names.
Column 1 is dates and rest columns are numbers.
The dateformat being defined in the code is:
dFormat = struct;
dFormat.Style = struct( 'NumberFormat', '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(#_)' );
dFormat.Font = struct( 'Size', 8 );
Can someone please explain me what the dFormat.Style code means ?
Thanks
The first line creates an empty struct (struct with no fields) called dFormat. A structure can contain pretty much anything in one of its fields, including another structure. The second line adds a field called 'Style' to the dFormat struct and sets it equal to another struct with a field called 'NumberFormat'. The 'NumberFormat' field is set equal to that long string of characters. You now have a structure of structures. The third line is similar to the second.
Note that the first line isn't really necessary unless dFormat already exists and it needs to be "zeroed out" as dFormat.Style with create it implicitly. However, using the struct function can make code more readable in some cases as objects use a similar notation for access methods and properties. In other words, all of your code could be replaced with:
dFormat.Style.NumberFormat = '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(#_)';
dFormat.Font.Size = 8;
See this video from the MathWorks for more details and this list of helpful structure functions and examples.
#horchler already elaborated on structs, but I imagine you may actually be more interested in the content of this structs Style field.
In case you are solely interested in _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(#_), that does not really look like something MATLAB related to me.
My best guess is that this code is used to later feed some other program, for examle to build an excel file.

MATLAB missorting structure array when using dir command

I have a bunch of Excel data, called "1.xls", "2.xls"... until "15.xls", each with 141x44 sets of data. I am using the dir function to import the data into MATLAB.
Here I am importing the first and second columns from each file into A and B matrix.
prob15 = dir(fullfile('C:\Users\Bo Sun\Documents\MATLAB\prob15'),'.xls');
global A B
A=zeros(141,length(prob15));
B=zeros(141,length(prob15));
for i=1:length(prob15)
A(:,i) = xlsread(prob15(i).name,'A:A');
B(:,i) = xlsread(prob15(i).name,'B:B');
end
My problem is, when I use the dir command, for some reason MATLAB missorts the data, in that the ascending order of the prob15 structure array will be "1.xls", "10.xls", "11.xls"... instead of normal ascending numerical order ("1.xls", "2.xls, ...). Anyone know how I could fix this? Thanks.
The order you are seeing is called ascii-betical order and is the normal sorting order for all kinds of utilities, and evidently your OS directory listing program as well, since matlab just farms this command out to the OS.
If you want a numerical sort, you can convert the filename strings to numbers and sort those. Before I wrote it myself some light googling yielded this which you can easily adapt to your problem:
list = dir(fullfile(cd, '*.mat'));
name = {list.name};
str = sprintf('%s#', name{:});
num = sscanf(str, 'r_%d.mat#');
[dummy, index] = sort(num);
name = name(index);