How can I create dynamic variables A1, A2,...,A10 in a loop and save them?
Show older comments
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:
- Suppose that you are using some functions and you want to loop their arguments (arg) to get different results.
- In each iteration you want to save a variable and name it using the current arguments
- 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
Matt J
on 11 May 2017
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.
@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:
John D'Errico
on 12 May 2017
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.
"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.
John D'Errico
on 16 May 2017
If you insist on doing something foolish, nobody can stop you. Did you bother to look at the link Jan gave you?
Rik
on 16 May 2017
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)?
Rik
on 16 May 2017
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)?
MikCh
on 16 May 2017
Stephen23
on 16 May 2017
@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):
@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.
- "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).
- 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.
- Yes.
- 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.
- Yes.
- 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.
Answers (2)
Rik
on 11 May 2017
1 vote
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
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!