How can I modify a list of existing variables programmatically?
5 views (last 30 days)
Show older comments
I've been given a set of recorded data for a bunch of signals, for example the list of column vectors "a", "b", "c", "d", "e" in a mat file. I know the names of the variables are a, b, c, d, e. In order for these recorded signals to be useful to me, I need to prepend them with a known vector of sample times, for example [1; 2; 3; 4; 5]. So as an example, I could manually do this operation like this:
load("recordedVars.mat"); % suppose this gives a = [2; 4; 6; 8; 10] as recorded data and something similar for b, c, d, e
times = [1; 2; 3; 4; 5]; % known vector of times to assign to each variable
a = [times, a];
b = [times, b];
c = [times, c];
d = [times, d];
e = [times, e];
Is there a programmatic way to do this job to scale up for more than 5 variables? In pseudocode what I'm imagining is:
Load Data
For each name in list of names
assign name = [times, name]
End
Is it possible to iterate on variable names in this way?
My actual application involes going on to use the modified a,b,c,d,e by loading them into simulink via "From Workspace" blocks with the given names, so I don't think assigining a bunch of new variables would save work.
0 Comments
Answers (2)
Walter Roberson
on 20 Sep 2023
Please read http://www.mathworks.com/matlabcentral/answers/304528-tutorial-why-variables-should-not-be-named-dynamically-eval for information about why we strongly recommend against creating variable names dynamically.
It is possible -- but it error prone and difficult to debug. I would say that you should not consider using it in your own code unless (at the very least) you can identify the problems with the code at https://www.mathworks.com/matlabcentral/answers/2020976-i-want-to-store-the-vector-from-each-for-loop-iteration-how-can-i-do-this#answer_1310391
3 Comments
Walter Roberson
on 20 Sep 2023
load("recordedVars.mat"); % suppose this gives a = [2; 4; 6; 8; 10] as recorded data and something similar for b, c, d, e
That command "poofs" variables into the workspace. Instead use
varstruct = load("recordedVars.mat");
Then varstruct would be a struct with one field for each variable loaded. You can then use dynamic field names,
fn = fieldnames(varstruct);
times = varstruct.times;
fn = setdiff(fn, 'times');
for K = 1 : length(fn)
thisdata = varstruct.(fn{K});
thisdata = [times, thisdata];
assignin('base', 'DataToLoad', thisdata);
sim(....)
end
where the model uses From Workspace to load DataToLoad
Steven Lord
on 20 Sep 2023
If you must do this, call load with an output argument. Iterate over the fieldnames of the struct that load returns and use dynamic field names to access those fields. This allows you to avoid having an unknown number of variables with unknown names (which could potentially overwrite existing variables) in your workspace.
data = load('census.mat')
f = fieldnames(data) % variables in the MAT-file
for whichvar = 1:numel(f)
name = f{whichvar};
thevar = data.(name); % dynamic field names
sz = mat2str(size(thevar));
fprintf("Variable %s from census.mat has size %s.\n", name, sz)
end
If I'd had a variable named pop in my workspace and tried to load this MAT-file, the variable would have been overwritten as you can with the example below.
pop = 42 % The Answer to Life, the Universe, and Everything
load('census.mat')
pop % No longer the Answer
the cyclist
on 20 Sep 2023
You've seen @Walter Roberson's answer, and it is spot-on. That being said, what you want to do is possible, using the appropriately-reviled eval function. Here is a miniature version of what you want to do:
times = [1;2;3];
a = [2;3;5];
b = [7;11;13];
varList = ["a","b"];
for v = varList
eval(v+" = [times, "+v+"];");
end
You can see even in this small example how ugly and error-prone coding like this can be.
2 Comments
the cyclist
on 20 Sep 2023
An arguably cleaner variant of this solution is to write out the string you want executed using the sprintf function:
times = [1;2;3];
a = [2;3;5];
b = [7;11;13];
varList = ["a","b"];
for v = varList
eval(sprintf("%s = [times, %s];",v,v));
end
But, from experience I know that folks sometimes have a difficult time grokking sprintf, so I didn't want to only use that as a solution.
See Also
Categories
Find more on Environment and Settings 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!