How can I create dynamic variables A1, A2,...,A10 in a loop and save them?

Hello community! I have seen that this question is timeless, with several modifications, but most cases are general. So the script that puzzles me has the following setting:
  1. Suppose that you are using some functions and you want to loop their arguments (arg) to get different results.
  2. In each iteration you want to save a variable and name it using the current arguments
  3. Finally, all the variables created should be saved in a new .m file.
Schematically,
for arg1 = 0.1:+0.1:1.5
for arg2 = 0.1:+0.1:1.5
for arg3 = 0.1:+0.1:1.5
for arg4 = 0.1:+0.1:1.5
Object1 = function(arg1, arg2)
Object1.Specification = function(arg3, arg4)
Variable_arg2_arg4 = function(Object1) % *
save(fullfile(path, name), all variables created) % **
end
end
end
end
The steps that trouble me are those highlighted with [*] and [**].
I know that a vectorized method for saving the variables created in each iteration is more clear-cut, but in this case I cannot think of a better solution other than creating them dynamically. However, any suggestion is greatly appreciated!

17 Comments

I have seen that this question is timeless
I'm surprised you have not seen the timeless answer ... that you should not do this ;)
@MikCh: what do you intend to do with those variables, once they are saved? If you give us some more information about the whole workflow, then we could give much more useful advice. For example, contrary to what some users apparently think, it is much much easier to save and load multiple .mat files in a loop if they contain exactly the same variable names. In fact using different names requires all kinds of fiddling around... and yet those users unfortunately seem to believe that they should name every variable in each file with a different name.
Designing how the data is arranged and how the code should work depends on the use-case, which you have told us absolutely nothing about.
Remember that putting meta-data into variable names makes code much more complicated and buggy, so it is almost always much better to not change the variable name.
@Stephen Cobeldick: Thank you very much for your response.
The workflow is as described in 1-3 steps. I need to save all created variables in a separate .m file so as to load them in another script (step 4) that gets information from the variable's name to perform further analysis (i.e. plots, statistics, etc).
I think that in this way, it is more handy to keep track on how these variables have been created.
@MikCh: thank you for the brief explanation of the next step in the workflow. Rather than naming variables dynamically, a much simpler way of achieving what you want would be to store the meta-data as data in its own right (rather than trying to munge it into variable names), e.g.:
data = [1,2,3];
make = 'Ford';
model = 'Fiesta';
save('file.mat','data','make','model')
...
data = [4,5,6];
make = 'Skoda';
model = 'Octavia';
save('file2.mat','data','make','model')
...
etc
Not only is this trivial to save in a loop, it is also trivial to load in a loop, which makes your step 4 very simple too. The reason is because meta-data is much better stored as data, rather than trying to be used awkwardly in variable names.
"...that gets information from the variable's name..."
That would be about the worst way of passing information. Putting data into and getting it out of variable names is really awkward (and buggy, slow, ...). But because "information" is data, it can be simply stored in those files like all the other data. Then saving, loading, and using those variables and files is trivially easy.
"I think that in this way, it is more handy to keep track on how these variables have been created"
Nope. It is much simpler (and faster, more reliable, easier to read, easier to debug) to just store your meta-data as data. See also:
Do you really think that a1, a2 is easier to "keep track of" than a(1), a(2), etc? Or to know how they were created? In fact, having ONE variable, a, is FAR SIMPLER to keep track of.
Your code, written with numbered variables as you want to use will be slow. Inefficient. It will be prone to bugs.
Learn to use arrays in all shapes and forms, cell arrays, struct arrays. All of them can solve the problem that you have, and do so far better than using numbered variables.
@Stephen Cobeldick: Thank you for the advice! Unfortunately, I am not that much familiar with storing meta-data but I will give it a try!
I have read a lot about avoiding to use eval and since I haven't used this function before I am not intending to do so now.
Let me just restate the problem and see whether I can further clarify the issue I am facing:
  • In step [*] of the code I get as output, of the function that follows, a column vector of length 100. I want to give a name to this variable according to the argument values that I have for the current iteration (i.e. Variable_arg2_arg4 ).
  • In step [**] I want this variable to be saved in a .m file in order to use it in another script.
At the end of this loop, I expect to have a new .m file that will include all the variables that have been created and named after those arguments.
Including the values of the arguments in the name of the variable is crucial for the next step of the analysis, that's why I insist on this strategy.
Thanks again!
P.S. Excuse my fuzziness but my level of proficiency in Matlab is not that much high! Maybe adding a label for the experience of the user that asks a question might be an informative addition for the forum!
"Including the values of the arguments in the name of the variable is crucial for the next step of the analysis, that's why I insist on this strategy."
Can you please explain why this is "crucial", because thus far none of us can see why this would be the case. And based on your earlier very brief explanation: "to load them in another script (step 4) that gets information from the variable's name to perform further analysis (i.e. plots, statistics, etc)", dynamic variable names would not be required for passing meta-data at all (and would just make your code slower and buggier than it needs to be).
So far everything you have explained could be solved quite simply using indexing and storing the meta-data together with the rest of your data. I am curious what makes it "crucial" to use dynamic variable names.
I suppose that this cruciality relates to way that the remaining process of analysis is organized.
However, the initial question is still there: how one can efficiently save variables, for a multiple-loop framework, in a separate .m file and keep their properties (i.e. the arguments of each iteration) either as an extension of the name or in any other tractable form.
An illustrative example would be highly appreciated!
If you insist on doing something foolish, nobody can stop you. Did you bother to look at the link Jan gave you?
I absolutely second John's comment.
My question is why my answer is not good enough for you (i.e. saving the information in the filename)?
I absolutely second John's comment.
My question is why my answer is not good enough for you (i.e. saving the information in the filename)?
@ John D'Errico: I tried to use all approaches suggested both in Matlab forum and elsewhere but didn't find anything that resembles a multiple-loop case.
So, I thought that stating in details the problem and asking for advice, supported by specific directions, from experienced users would be a non-foolish way of resolving this issue.
Hence, the problem boils down to "which are the best practices to tackle steps [*] and [**] in multiple-loop framework?"
@MikCh: Your answer to my question: "I suppose that this cruciality relates to way that the remaining process of analysis is organized", does not make it any clearer to me why these variables must be dynamically named: you seem to be conflating "I want to store some meta-data together with my data" with "I need to use dynamic variable names", but these are not synonymous (and indeed one of them makes for slow, buggy code). Store the meta-data in its own array/s, and this is then trivial to access using the same methods as the data itself.
If you want an efficient solution of passing (meta-)data by saving it in multiple files, then simply use a cell array/ND array/structure/table/etc with indexing in a loop: the MATLAB documentation shows how to use indexing, and access files in a loop (and yes, there are examples):
@ Stephen Cobeldick: Thanks again you for the resources! They are quite helpful.
If I am getting it right, you suggest to break down step [*] in two actions:
  1. create a cell variable, in a sequential way, containing the properties of the iteration (1st link attached)
  2. create a matrix ("MatrixOfResults") that will store the resulting values created from this function (2nd link attached)
So the code provided above, would look like this:
for arg1 = 0.1:+0.1:1.5
for arg2 = 0.1:+0.1:1.5
for arg3 = 0.1:+0.1:1.5
for arg4 = 0.1:+0.1:1.5
fileNames = sprintf('Variable_%.2f_%.2f', arg2, arg4);
Object1 = function(arg1, arg2)
Object1.Specification = function(arg3, arg4)
MatrixOfResults[...] = function(Object1) % ***
end
end
end
end
Now, please let me ask some further questions:
  • should I predefine the number of variables that would be created? If so, could you please provide a link?
  • how I can attach/index the results of the function highlighted in [***] (i.e. what indices should be used in the "MatrixOfResults" part of this line)?
  • finally, how this could work for saving them in a .m file as well?
Thanks again!!
@MikCh: your indexing will be something like this (I used two loops to make this example simpler, and used more meaningful variable names (this helps make code less buggy)):
vSpeed = [1,2,3,4,5];
vHeight = [6,7,8,9];
dataC = cell(numel(vSpeed),numel(vHeight));
for kSpeed = 1:numel(vSpeed)
for kHeight = 1:numel(vHeight)
obj = fun(vSpeed(kSpeed),vHeight(kHeight));
...
filename = sprintf('File_%s_%s.mat',....)
fpath = fullfile(dpath,filename);
save(fpath,'obj','kSpeed','kHeight');
end
end
Note that your four nested loops are going to be extremely inefficient: the two operations are not dependent on the same loop variables:
... = function(arg1, arg2)
... = function(arg3, arg4)
which means that you will call each of them repeatedly on every iteration when this is not required because you will get exactly the same output. This is a classic cause of beginners writing slow code: repeating operations in a loop when they could be performed fewer times outside the loop (or shifted up a few loop levels).
"finally, how this could work for saving them in a .m file as well?"
It won't. M-files are not intended for storing data. M-files are for writing scripts and functions. If you want to store data, then the easiest way is to use a .mat file, which is specifically designed for storing data (not code). And using it in your loop will be trivial: my code above shows this.
@ Stephen Cobeldick: Thanks for the super informative answer!!
Let me modify a bit the code that you have provided and comment on the procedure:
vSpeed = (0.1:+0.1:1.5);
vHeight = (0.1:+0.1:1.5);
dataC = cell(numel(vSpeed),numel(vHeight));
for kSpeed = 1:numel(vSpeed)
for kHeight = 1:numel(vHeight)
obj = function(vSpeed(kSpeed),vHeight(kHeight));
filename = sprintf('File_%.2f_%.2f.mat', vSpeed, vHeight);
fpath = fullfile(dpath,filename);
save(fpath,'obj','kSpeed','kHeight');
end
end
Steps of Stephen's approach:
  1. vSpeed & vHeight: In the first two lines you translate the iterations into variables so as to avoid over-looping
  2. dataC: you create a cell that stores the name of the variables? (I'm not sure about that since you do not use it inside the loop)
  3. obj: here you run the function using an indexing method for the arguments
  4. filename: you print a mat file for each iteration. The name of the mat file includes the arguments of the iteration.
  5. fpath: you create the path where the specific mat file will be saved
  6. save(...): you save the items 'obj','kSpeed','kHeight' into the file
When I do run this code, the following points arise:
  • I think that storing 'vSpeed' and 'vHeight', as being the actual parameters of the equations, might be better instead of storing 'kSpeed' and 'kHeight'.
  • How should I use the dataC cell?
  • The way that filename appears in the loop, gives back a char object (size 1x270) that goes like this: "file_0.10_0.20.matfile_0.30_0.40.matfile_0.50_0.60.matfile_0.70_0.80.matfile_0.90_1.00.matfile_1.10_1.20.matfile_1.30_1.40.matfile_1.50_0.10.matfile_0.20_0.30.matfile_0.40_0.50.matfile_0.60_0.70.matfile_0.80_0.90.matfile_1.00_1.10.matfile_1.20_1.30.matfile_1.40_1.50.mat" Hence, I am doing something totally wrong!
  • what is "dpath" inside the fullfile?
  • Your suggestion is to store each variable in a separate mat file?
Thanks again for your feedback!
p.s. sorry for the confusion about .m and mat files, I was referring to mat files
  1. "In the first two lines you translate the iterations into variables so as to avoid over-looping"... errr, I have no idea what that means. I created the vectors vSpeed and vHeight simply because then the loop variables kSpeed and kHeight can be indices (i.e. integers from one). Iterating over indices is often more useful than iterating over values (for example here it makes saving the values in vSpeed and vHeight easier, because they are in simple vectors which are easy to handle).
  2. That line does nothing useful here. I simply forgot to remove it. In any case, it does not store the names of any variables, it simply creates a cell array of empty cells, which is then never used. You ca get rid of this line. (Lines like this are useful when calculating values in a loop, and then putting them into an array). The reason I used two variables was because I did not want to make the example complicated. You can use four, or five, or however many vectors of values that makes you happy.
  3. Yes.
  4. sprintf creates a 1xN char array. The documentation calls it "format data into string". Using the term "print" is a bit misleading, as it does not send any data to the stdout or the like.
  5. Yes.
  6. Yes.
And your points:
  • You will could store both, or just vSpeed and vHeight. Whatever suits your needs. Note that using indices might be simpler in the filenames.
  • It is not used unless you want to join some data into one array. Otherwise ignore Cdata.
  • The absolute or relative path of the location where the files are to be saved. Do not cd to that directory, and there is no point in cluttering up your current directory with files like that, when using absolute or relative paths makes it trivial to read/write files anywhere. Read the help for fullfile.
  • "Your suggestion is to store each variable in a separate mat file?" No, that was just what you showed in your question. I have no idea about your data: how many samples there are, if they are contiguous, what format they is stored in, if it takes 100 kB or 100 TB of storage, how you want to access them, etc etc. Without concrete examples or specifications of your data I am not going to waste my time guessing how it should be stored. Maybe one variable per file is efficient, or then again maybe not. For small-medium amount of data, most likely not. It might be more efficient to write the data to file after the loops (and then you will need to use Cdata or something similar, like an ND array). As I have no idea how much data you have, whether it is numeric or string, or something else entirely, I will not make any guesses.

Sign in to comment.

Answers (2)

You could use eval to do what you are asking, BUT YOU SHOULD NOT DO THAT.
Instead you could use the values of the arguments to generate a file name that does this. For that sprintf is all yours to play with. Type doc sprintf to find out everything you can do with it.
You should try to rework this, so you can remove some of the inefficiency here. One of the more easier ways to this is generating a cell matrix, so you can use cellfun to run every combination you need.

Categories

Find more on Scope Variables and Generate Names in Help Center and File Exchange

Asked:

on 11 May 2017

Edited:

on 16 May 2017

Community Treasure Hunt

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

Start Hunting!