MATLAB Answers

3

Create a structure name based on the string of a variable. Create fieldnames in this structure.

Latest activity Commented on by Guillaume
on 10 Nov 2017
Inside a function I have a variable called name which is a char class. I want to generate a structure based on the string of variable *name *and then create fields in this structure.
name =
report 1
I do the following to create a variable with the string of variable name.
v=genvarname(strrep(name, ' ', '_'));
Then in my function I have created other variables which have certain values. I want to create fieldnames in the previous structure with the name of these variables. Those fieldnames will have the same value as the corresponding value of the variable.
example:
a=mean([1 2 3 4]);
b=std([1 2 3 4]);
What I want to create is the following:
report_1.a= 2.5000
report_1.b=1.2910
My final goal is to create an output in the function with structure report_1.

  0 Comments

Sign in to comment.

Tags

6 Answers

Answer by Stephen Cobeldick on 1 Sep 2015
Edited by Stephen Cobeldick on 1 Sep 2015
 Accepted Answer

The simplest answer would be to use a non-scalar structure, which is exactly intended for this kind of data collection:
>> data(3).A = pi;
>> data(2).A = 0;
>> data(1).A = -Inf
>> data(3).B = 8;
>> data(2).B = 4;
>> data(1).B = 2;
>> mean([data.B])
ans =
4.6667
>> data(1).A
ans =
-Inf

  0 Comments

Sign in to comment.


Answer by Cedric Wannaz
on 17 Jun 2013
Edited by Cedric Wannaz
on 17 Jun 2013

Why do you want to do this? In my experience, cases where it is appropriate to define dynamically variables names are extremely rare. Dynamical field name generation is more frequent though.
In any case, your function's output arguments will be copied into variables that are define outside of the function, so there is no point in defining a structure name dynamically within the function. To illustrate..
function outStruct = myFunction(values, fieldNames)
outStruct.(fieldNames{1}) = sum(values) ;
outStruct.(fieldNames{2}) = mean(values) ;
end
.. and a call from elsewhere (command line, script, etc):
S = myFunction([5, 6, 7], {'a', 'b'}) ;
This leads to S being a struct with two fields: a = 18, and b = 6.
As you can see S is not known as a local variable within myFunction, but what will ultimately be S value is built under the local variable name outStruct within the function. So you see that if you wanted to generate a name for S dynamically, it would have to be done outside of the function. You also see how to define field names dynamically: myStruct.(fieldname1) = value1, etc.
But again, dynamically building variable names is rarely legitimate. If you wanted, for example, to read multiple files which include field names and values, and have their content stored in structs with these field names, you could create a cell array of structs indexed by a file ID if field names could vary among files, or a struct array if fields would be similar among files.

  2 Comments

I have created a function that allows me to open the browser, open a folder and choose certain files with data. The variable *name *grabs the name of the folder. So then I want to create a structure with the folder name and for fieldnames some variables inside the function. So when I rerun the function for another folder then in the workspace I will have the following structures. If folder name 1 is Data 1 and folder name 2 is Data 2. Then,
Data_1.a
Data_1.b
Data_2.a
Data_2.b
I will have then neatly organized the results of thousands of data in structures with the convenience that they will have the same name as the folder name.
One could list a variety of reasons not to create dynamically variables/names; I will just mention a practical one: as long as you are working "by hand" in the workspace, having these variables is fine, but if you wanted to use this approach in a more automated structure, you would have a "hard" time accessing the variables in the base workspace/stack from any function for example, and it would not be that easy to pass them to functions during function calls.
Have you thought about grouping all these variables under an overarching struct? To illustrate
Content = struct() ;
for k = 1 : nFolders
folderName = ... % E.g. 'Data 1'
folderFieldName = ... % E.g. 'Data_1'
Content.(folderFieldName) = readFolder( folderName, ... ) ;
end
Using your example above, you would have
Content.Data_1.a
Content.Data_1.b
Content.Data_2.a
Content.Data_2.b
which you could easily browse, pass as a whole or by block to a function, etc. Getting field names in an automated mechanism would also be easier to implement than accessing variables from the base stack.

Sign in to comment.


Answer by Tom
on 17 Jun 2013

You can make a function to process the names into a structure:
function out = Var_Names(varargin)
for n = 1:nargin
out.(inputname(n)) = varargin{n};
end
Then run:
a=mean([1 2 3 4]);
b=std([1 2 3 4]);
s = Var_Names(a,b);
To give the structure its required variable name, you can run
name = 'report 1';
eval([genvarname(name),' = s'])
As everyone will tell you, it's not good to use the EVAL function, so instead it might be better to add a field to the structure with the name, e.g.
s.StructName = genvarname(name);

  1 Comment

Sign in to comment.


Answer by Andrei Bobrov
on 17 Jun 2013

report_1 = cell2struct(num2cell([mean(1:4) std(1:4)]),{'a','b'},2);

  1 Comment

But I don't know know before hand the string of name. In this case is
report 1
What happens when it the variable name is
report 2
So I want the name of the structure to change dynamically.

Sign in to comment.


Answer by PAPADAKIS IOANNIS on 28 Oct 2016

Hi Giorgos I have a similar problem. I read data from excel where the column names are stored like Speed_55m.max Speed_55m.min Speed_55m.stdev Speed_55m.value. That repeats for different heights. I use [a,b]=xlsread('IEA_Task32_Dataset_PP_RR.xlsx'); and then I would like to use a for loop to create structures
Something like that for icol=1:size(a,2) char(b{icol})=a(:,icol); end
my target is for different height to create a structure where I have data for max, min and std

Answer by msand65
on 10 Nov 2017
Edited by msand65
on 10 Nov 2017

I wrote a simple function many years ago ("remove_bad_chars.m") that replaces the characters not allowed in a structure name (using strrep and regexprep mostly) with acceptable characters for a structure name. There is a little more to it than that (can't start with a number or _, replace _ _ with _ etc) but it is a simple function that I have been adding to through time as I run into a new character that a structure name can't contain or header names that are more complex.
For example, say I read in a CSV file and the first row of that file contains the column names. Suppose one header is 'temp (K)', this function changes it to 'temp_K'. Then I can implore the use of dynamic structures to assign the column of data to a structure with that fieldname, say data.temp_K.

  2 Comments

There are a couple functions for that purpose in MATLAB. If you're using release R2014a or later, use matlab.lang.makeValidName. You may also want to use matlab.lang.makeUniqueStrings if you have a cell array of field names and you want to make sure none of them conflict once you've made them valid MATLAB identifiers.
For older releases, see genvarname.
Note that if you use makeUniqueStrings after makeValidName, you have to be careful that makeUniqueStrings does not generate names that are too long and thus invalid variable names. Even Mathworks got that workflow wrong in the implementation of matlab.internal.json.makeStructure in R2017a (fixed in R2017b).
%some invalid variable names
v = {[repelem('a', 70), 'a']; [repelem('a', 70), 'b']}
%will generate invalid variable names:
newv = matlab.lang.makeUniqueStrings(matlab.lang.makeValidName(v))
%proper usage:
newv = matlab.lang.makeUniqueStrings(matlab.lang.makeValidName(v), 1:numel(v), namelengthmax)

Sign in to comment.