I have a number of vectors containing data that i have to elaborate in the same way, they are named in this fashion: "data1", "data2" ecc... I would like to automatize the process with a for cycle, how can i "select" iteratively the variables using the index?
For example, the first line of my elaboration is an assignment like "x = data1", i want the second cycle to do "x = data2" and so on.
Thank you in advance
You can use a combination of strcat and num2str to create the name of the variable
i = 1;
name = strcat("data",int2str(i));
Thus putting it inside a for-loops which updates i will continuously change the name. Next you can use eval to evaluate the name
x = eval(name);
In total
for i = 1:n
name = strcat("data",int2str(i));
x = eval(name);
end
NOTE 1: It is in general considered bad practice to create variable names this way. You would have been much better off with saving all variables in the same array. As linked by Luis Mendo in the comments.
NOTE 2: It is generally recognised as a for-loop, not a for-cycle :D
Related
I am a beginner in Matlab and have not been able to find an answer to my question so far. Your help will definitely be very much appreciated.
I have 70 matrices (100x100), named SUBJ_1, SUBJ_2 etc. I would like to create a loop so that I would calculate some metrics (i.e. max and min values) for each matrix, and save the output in a 70x2 result matrix (where each row would correspond to the consecutively named SUBJ_ matrix).
I am struggling with both stages - how to use the names of individual variables in a 'for' loop and how to properly save individual outputs in a combined array.
Many thanks and all the best!
Don't use such variable names, create a big cell array named SUBJ and put each Matrix in it.
r=zeros(numel(SUBJ),2)
for idx=1:numel(SUBJ)
r(idx,1)=min(min(SUBJ{idx}))
r(idx,2)=max(max(SUBJ{idx}))
end
min and max are called twice because first call creates maximum among rows, second call among columns.
Even though this is in principle possible in Matlab, I would not recommend it: too slow and cumbersome to implement.
You could instead use a 3-D matrix (100x100x70) SUBJ which would contain all the SUBJ_1 etc. in one matrix. This would allow you to calculate min/max etc. with just one line of code. Matlab will take care of the loops internally:
OUTPUT(:,1) = min(min(SUBJ,[],1)[],2);
OUTPUT(:,2) = max(max(SUBJ,[],1)[],2);
Like this, OUTPUT(1,1) contains min(min(SUBJ(:,:,1))) and so on...
As to how to use the names of individual variables in a 'for' loop, here gives an example:
SUBJ = [];
for idx = 1:70
term = eval(['SUBJ_',num2str(idx)]);
SUBJ = [SUBJ; max(max(term)),min(min(term))];
end
I would like to change values within an dataset using eval. It shlould be in a way thet every second value is changed to the one before.
Short example:
A = magic(6)
ds = mat2dataset(A) % original dataset
ds.A1(2:2:end) = ds.A1(1:2:end) % dataset after change
That's the way I would like to do it. Now I need to use the variables letter and number which are assigned previous in the function.
letter = 'A'
number = '1'
eval([strcat('ds.', letter, number)]) % now gives me all values.
This is exactly the point where I would like to index the (1:2:end) to get just the indexed values.
Does one of you have a good idea how to index within the eval function? I would also prefer other ways of doing it if you have on.
Thanks a lot!
1) Don't use eval to achieve dynamic fieldnames:
h=ds.([letter, number])
2) Double indexing is not possible, you need two lines to achieve it.
h(1:2:end)
I have two mat files with identical list of variables.
In file1.mat
*Variables* *Value* *Type*
Time [100X1] double
Force [100x1] double
In file2.mat
*Variables* *Value* *Type*
Time_1 [90X1] double
Force_1 [90x1] double
I would like to vertically concatenate these two files. The suffix _1 added to the file2 changes to _2 or _32 etc.
How can I refer the variables and concatenate them in a loop so I don't have to open the file every time and enter the variable names in vertcat?
You can use two nice properties of the load command for this task. Firstly, load with an output argument creates a structure with field names equal to the variable names, which means that you can load data without having to know ahead of time what the variables were named. Secondly, the fields are assigned in alphabetical order, which means that force will always be the first field, and time the second field.
Combining these properties, you can do the following:
%# get a listing of all save files
fileList = dir('file*');
nFiles = length(fileList);
loadedData = cell(nFiles,2); %# for storing {force,time}
%# loop through files and write results into loadedData
for iFile = 1:nFiles
tmp = load(fileList{iFile});
loadedData(iFile,:) = struct2cell(tmp)';
end
%# catenate
time = cat(1,loadedData(:,2));
force = cat(1,loadedData(:,1));
Note that if your files are called file1...file10, instead of file001...file010, the alphabetical ordering you get from using the dir command may not be ideal. In that case, you may have to extract the number at the end of the file name and re-order the list.
Does the following code snippet help to solve your problem?
Time_1 = [1; 2];
Time_2 = [2; 3];
Time_3 = 4;
All = [];
for i = 1:3
CurTime = eval(horzcat('Time_', num2str(i)));
All = [All; CurTime];
end
Essentially what is happening is I'm looping over the suffixes of Time_1, Time_2, and Time_3. For each iteration, I obtain the pertinent Time_x variable by manually building the name of the variable in a string, and then allocating it to CurTime using the eval function. Then simply perform the desired concatenation using CurTime
Of course, this code is not very efficient as All is growing within the loop. If you know the size of All beforehand, then you can pre-allocate it. If the size is unknown before the fact, you can implement the solution here (or else just pre-allocate it as being arbitrarily large and then cut it down to size once the loop is complete).
Let me know if I've misunderstood the problem you're having and I'll try and come up with something more helpful.
Also, some people think eval is evil. Certainly if your code contains 10 different calls to eval then you're probably doing it wrong.
I am trying to use MATLAB in order to generate a variable whose elements are either 0 or 1. I want to define this variable using some kind of concatenation (equivalent of Java string append) so that I can add as many 0's and 1's according to some upper limit.
I can only think of using a for loop to append values to an existing variable. Something like
variable=1;
for i=1:N
if ( i%2==0)
variable = variable.append('0')
else
variable = variable.append('1')
i=i+1;
end
Is there a better way to do this?
In MATLAB, you can almost always avoid a loop by treating arrays in a vectorized way.
The result of pseudo-code you provided can be obtained in a single line as:
variable = mod((1:N),2);
The above line generates a row vector [1,2,...,N] (with the code (1:N), use (1:N)' if you need a column vector) and the mod function (as most MATLAB functions) is applied to each element when it receives an array.
That's not valid Matlab code:
The % indicates the start of a comment, hence introducing a syntax error.
There is no append method (at least not for arrays).
Theres no need to increment the index in a for loop.
Aside of that it's a bad idea to have Matlab "grow" variables, as memory needs to be reallocated at each time, slowing it down considerably. The correct approach is:
variable=zeros(N,1);
for i=1:N
variable(i)=mod(i,2);
end
If you really do want to grow variables (some times it is inevitable) you can use this:
variable=[variable;1];
Use ; for appending rows, use , for appending columns (does the same as vertcat and horzcat). Use cat if you have more than 2 dimensions in your array.
I run through a for loop, each time extracting certain elements of an array, say element1, element2, etc. How do I then pool all of the elements I've extracted together so that I have a list of them?
John covered the basics of for loops, so...
Note that matlab code is often more efficient if you vectorize it instead of using loops (this is less true than it used to be). For example, if in your loop you're just grabbing the first value in every row of a matrix, instead of looping you can do:
yourValues = theMatrix(:,1)
Where the solo : operator indicates "every possible value for this index". If you're just starting out in matlab it is definitely worthwhile to read up on matrix indexing in matlab (among other topics).
Build the list as you go:
for i = 1:whatever
' pick out theValue
yourList(i) = theValue
end
I'm assuming that you pick out one element per loop iteration. If not, just maintain a counter and use that instead of i.
Also, I'm not assuming you're pulling out your elements from the same position in your array each time through the loop. If you're doing that, then look into Donnie's suggestion.
In MATLAB, you can always perform a loop operation. But the recommended "MATLAB" way is to avoid looping:
Suppose you want to get the subset of array items
destArray = [];
for k=1:numel(sourceArray)
if isGoodMatch(sourceArray(k))
destArray = [destArray, sourceArray(k)]; % This will create a warning about resizing
end
end
You perform the same task without looping:
matches = arrayfun(#(a) isGoodMatch(a), sourceArray); % returns a vector of bools
destArray = sourceArray(matches);