How can I change variable names in a for loop?

Hi,
I have exported some simulation results from another software to MATLAB. Now I have 27 variables with names such as vN1a,vN2a....vN27a. I am trying to get max value of each variable using for loop. The problem is I don't know how I can change the numbers in the names of my variables. Some people use eval function, but here the case is a bit different.
Here is my code
clc,clear
format short g
v_max = zeros(27,1);
load('Filename.MAT');
for x=1:1:27
v_max(x,1) = v_max(x,1) + max(vN1a); % I tried max(vNxa), but it didn't work at all.
end
v_max
any suggestions?

5 Comments

Do it without eval! Hint:
A = 1;
B = 2;
C = 3;
save
outputs
Saving to: h:\m\cssm\matlab.mat
Next
S = load()
outputs
Loading from: matlab.mat
S =
A: 1
B: 2
C: 3
Finally
field_name_list = permute( fieldnames( S ), [2,1] );
for name = field_name_list
disp( max( S.(name{:}) ) )
end
outputs
1
2
3
Thanks for your prompt response and useful guidance.
Note that there is still some trickiness here, and I am not entirely sure that the algorithm using the structure does exactly what you want.
DISCLAIMER: I don't want you (or anyone!) to think I am advocating the use of eval in general. It is evil, for all the reasons described here.
BUT ... I don't yet see another solution for your specific problem.
Namely, you still need to get the values of vN1a, vN2a, ... into vmax -- in the correct (numerical) order.
There are two potential issues that I see with your case. There are likely workarounds, but it's good for you to be aware.
The first is that you might need to be careful if, in addition to the vN*a variables, you also have other ones in the *.mat file, then at some point you are going to need to filter those out, so that you do not include those in the vmax vector you want to create.
Even if that is not the case, there may be a second issue. Note that the fieldnames in the structure are going to be sorted alphabetically -- not numerically. So, if you use the for loop as in per isakson's nice solution, your vmax elements are not going to be in numerical order.
There are likely ways around these intricacies, so just be aware. Yet another reason to see if there is a way to go upstream and fix the original naming problem!
Stephen23
Stephen23 on 27 Jan 2016
Edited: Stephen23 on 27 Jan 2016
@the cyclist: I have already resolved both of these "issues" in my comments to your answer. Briefly:
  1. the fieldnames were specified using sprintf, thus only the desired fields were chosen.
  2. the fieldnames are generated in a loop, and the loop variable can be chosen to be in any order.
This neatly resolves both of these "issues". It should be noted that you also used sprintf in your Answer, to achieve exactly these aims (specific variables & sequence), but with slow, buggy eval instead of fast and neat fieldnames. There is absolutely no "trickiness" involved, just some fast, simple, reliable code without using eval.
Oh, sweet! Sorry for the redundant comment because I missed that.

Sign in to comment.

 Accepted Answer

You can find words of wisdom all over this forum about why it is a terrible idea to names variables a1, a2, a3, etc.
However, if your hands are absolutely tied, and you have no choice but to work with such variable names (because of an outside program that you had no control over), then eval might be your only option.
In your case, I think the following line does what you want:
eval(['v_max(x,1) = v_max(x,1) + max(vN',sprintf('%d',x),'a)'])
Note that what I did there was to split up the string to be evaluated into parts, and then used sprintf to convert the numerical variable x, and insert it into the string where needed.

7 Comments

Thanks a million. It has worked perfectly for me. I agree generating variables A1,A2... is not a good choice , however, in my case, all such variables were generated in another software. I had no control over them. Thanks again.
Actually you did have a choice, when you imported those data into MATLAB. If they are stored in a .mat file then this is trivial to achieve:
S = load(filename);
will load them into a structure, no dynamically named variables are required.
When those data were imported into MATLAB you had the choice to do it in a reliable way, but you chose to use buggy, slow and evil eval. Better data planning will make the rest of your code much neater, faster and more reliable.
Here is more information on why using eval is a poor choice, even though beginners love using it:
Thanks for taking the time to respond Stephen. Using structure command doesn't seem to solve my problem. My . MAT file contains hundreds of variables. There is no particular sequence of their appearance in structure variable. For instance, If I loop s.variable name, the problem is still there. How will I change variable name in s.variable then? I think eval function is the best solution , at least for me .
"How will I change variable name in s.variable then?": you can simply use dynamic fieldnames, like this:
S.(variable)
per isakson even told you this seven hours ago in a comment to your original question, showing how to use dynamic fieldnames, and with clear examples.
Here is another example, showing how to iterate over all variables in the .mat file, after loading them into one structure S, and without using eval:
S = load(filename);
N = fieldnames(S);
for k = numel(N)
N{k} % fieldname as a string
S.(N{k}) % value of that field (data)
end
Using dynamic fieldnames also makes it easy to sort the fields, add them, remove them, or take subsets of them, because they are all stored in one variable S. There are lots of inbuilt functions to manipulate structures. Because there is only one structure S it can be easily passed to other functions, or iterated over as in that example.
By comparison the method you are using loads everything into your workspace, potentially overwriting any variable that is already there (without warning). Then you use eval to try to access those random variables, which is much slower, much buggier, is not secure, and is very difficult to debug.
You should take a look at this tutorial:
which gives the following example (labelled BAD and GOOD):
a.doug = Hull
a.jiro = Doke
name = doug;
last = a.doug
eval([last = a.name]) %BAD
last = a.(name) %GOOD
You see, even TMW/MATLAB recommends that you use dynamic fieldnames, and to not use eval. Loren's blog also explicitly advises to use dynamic fieldnames and NOT to use eval. It still amazes me how many beginners think they know better than MATLAB themselves!
Let me explain what exactly I wanna do.
Below are some of the variables from your recomended method. some values of s;
s.(vN13a) has the position 1 in s. I only need vN values from 1a to 27a . Now tell me how I should write code for extracting only these 27 values out of these variables by using for loop.
I was wondering why MATLAB is not throwing this culprit out of MATLAB if it was such a bad guy of MATLAB. After reading few posts, now I think for many friends it's not the eval function; it's an evil function.
vN13a: [666668x1 double]
vN13b: [666668x1 double]
vN13c: [666668x1 double]
vN15a: [666668x1 double]
vN15b: [666668x1 double]
vN15c: [666668x1 double]
vN17a: [666668x1 double]
vN17b: [666668x1 double]
vN17c: [666668x1 double]
vN10a: [666668x1 double]
vN10b: [666668x1 double]
vN10c: [666668x1 double]
vN11a: [666668x1 double]
vN11b: [666668x1 double]
vN11c: [666668x1 double]
vN12a: [666668x1 double]
vN12b: [666668x1 double]
vN12c: [666668x1 double]
vN14a: [666668x1 double]
vN14b: [666668x1 double]
vN14c: [666668x1 double]
vN16a: [666668x1 double]
vN16b: [666668x1 double]
vN16c: [666668x1 double]
vN18a: [666668x1 double]
vN18b: [666668x1 double]
vN18c: [666668x1 double]
vN4a: [666668x1 double]
vN4b: [666668x1 double]
vN4c: [666668x1 double]
vN6a: [666668x1 double]
vN6b: [666668x1 double]
vN6c: [666668x1 double]
vN8a: [666668x1 double]
vN8b: [666668x1 double]
vN8c: [666668x1 double]
vN1a: [666668x1 double]
vN1b: [666668x1 double]
vN1c: [666668x1 double]
vN2a: [666668x1 double]
vN2b: [666668x1 double]
vN2c: [666668x1 double]
vN3a: [666668x1 double]
vN3b: [666668x1 double]
You can loop over the fieldnames using exactly the same tools you used to generate the eval strings, such as sprintf, because the fieldnames are also strings. sprintf is what the cyclist used in their answer, so why not try it here too?
I do not have your data, but this example should make it clear (with 'a', 'b', and 'c' fieldnames):
% structure, like from S = load(..)
S.vN1a = 1:3;
S.vN2a = 2:4;
S.vN3a = 3:5;
S.vN1b = Inf;
S.vN1c = NaN;
S.vN2b = Inf;
S.vN3b = Inf;
% loop over the 'a' fields:
for k = 1:3
fld = sprintf('vN%da',k)
S.(fld)
end
which displays the fieldnames and field values for the three fields with names ending with 'a', in the order determined by the for-loop (the order of the fields in the structure is not important here):
fld = vN1a
ans =
1 2 3
fld = vN2a
ans =
2 3 4
fld = vN3a
ans =
3 4 5
It printed exactly the data that we wanted (from the three 'a' fields), and none of the other data! Hurrah! You easily choose which fields you wish to work with, because you can either:
  • define the fieldnames yourself (like this example)
  • get the fieldnames from the structure and filter them
Both of these methods are neat, fast, secure, clear code, and simple to debug. Why do beginners love using slow, buggy, obfuscated, and insecure eval?
"I'm sorry Stephen I'm not convinced by your arguments." they are not my arguments. I did not invent the idea that eval is a stupid way to write code: I just read a lot of information, and learned why this is true.
Great. It's working without any problems. I've got your point now. Thanks for all the trouble you've taken to make things easier for me.

Sign in to comment.

More Answers (1)

Vs = {vN1a,vN2a....vN27a};
Now you can loop
for K = 1 : length(Vs)
vmax(K) = max(Vs{K});
end

1 Comment

The question arises how I can create Vs = {vN1a,vN2a....vN27a}; using a for loop if .MAT file has vN1a, vN2a......vN1000a,iN1a, iN2a......iN1000a.

Sign in to comment.

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!