How can I modify a list of existing variables programmatically?

5 次查看(过去 30 天)
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.

回答(2 个)

Walter Roberson
Walter Roberson 2023-9-20
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 个评论
Walter Roberson
Walter Roberson 2023-9-20
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
Steven Lord 2023-9-20
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')
data = struct with fields:
cdate: [21×1 double] pop: [21×1 double]
f = fieldnames(data) % variables in the MAT-file
f = 2×1 cell array
{'cdate'} {'pop' }
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
Variable cdate from census.mat has size [21 1]. Variable pop from census.mat has size [21 1].
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
pop = 42
load('census.mat')
pop % No longer the Answer
pop = 21×1
3.9000 5.3000 7.2000 9.6000 12.9000 17.1000 23.1000 31.4000 38.6000 50.2000

请先登录,再进行评论。


the cyclist
the cyclist 2023-9-20
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 个评论
the cyclist
the cyclist 2023-9-20
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.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Environment and Settings 的更多信息

产品


版本

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by