Borrar filtros
Borrar filtros

How can I modify a list of existing variables programmatically?

2 visualizaciones (últimos 30 días)
Alvin Allen
Alvin Allen el 20 de Sept. de 2023
Comentada: Alvin Allen el 20 de Sept. de 2023
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.

Respuestas (2)

Walter Roberson
Walter Roberson el 20 de Sept. de 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 comentarios
Walter Roberson
Walter Roberson el 20 de Sept. de 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
Steven Lord el 20 de Sept. de 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')
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

Iniciar sesión para comentar.


the cyclist
the cyclist el 20 de Sept. de 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 comentarios
the cyclist
the cyclist el 20 de Sept. de 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.
Alvin Allen
Alvin Allen el 20 de Sept. de 2023
Yep, that is ugly! Thanks though

Iniciar sesión para comentar.

Productos


Versión

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by