I want to store an array which changes its size in each iteration of a for loop.
For example,
for y=1:100
for x=1:50
.
.
ms(:,x,y) = ans;
.
.
end
end
The 'ans' is a row vector which changes its size in each iteration of y.
How can i store these variable length 'ans' into ms?
When i try to initialize 'ms' as cell, it shows an error saying "Conversion to cell from double is not possible."
What are the ways i can solve this?
Thanks
Kind regards
The only way I can think of is to indeed use a cell array. Initialize a 2D cell array like so:
ms = cell(50,100);
After, you index into the cell by using curly braces ({}). Therefore, your loop will look like:
for y=1:100
for x=1:50
.
.
ms{x,y} = ans;
.
.
end
end
After you're done, you can index into the cell array by choosing the row and column location you want:
vec = ms{row,col};
BTW, I don't recommend you use ans as a variable. ans is the default variable that is used when you execute a statement in MATLAB which has an output and you don't specify a variable of where this output from the function will go. You may have code that will overwrite the ans variable, so you should perhaps use another name.
One way to do this:
ms = {};
for y=1:100
for x=1:50
ms = [ms 1:x];
% or
% ms = [ms new_cell_element];
end
end
You can also index the cell array with ms{x,y} = 1:3;
new_cell_element does not need to be a cell, it can be anything you want.
ms = [ms, 'A string', (1:5).'] %// Works!
Note that I do not recommend this, and I'm pretty sure there are other ways to do this, depending on what you want to do inside those nested loops. You should check out cellfun, and read up on cells in general.
Also, never ever use ans as a variable name in MATLAB. That will only cause you trouble. Any other name is better (except clear and builtin).
Related
I have to run a Matlab loop indexed by x. At each iteration, I have to load and work with an array, A_x.mat, where the subscript x follows the loop index. How can I do that? Let me give you and example to highlight my issue. The example is very silly but serves my purposes.
X=10;
C=cell(X,1)
for x=1:X
load(['A_' num2str(x) '.mat']); %here I load A_x.mat
%C{x}=A_x*3;
end
I don't know how to compute A_x*3 in a way that allows the subscript x to vary. Could you advise?
To solve my issue I also tried
for x=1:X
B=load(['A_' num2str(x) '.mat']); %here I load A_x.mat and "rename" it B
%C{x}=B*3;
end
but B turns out to be a 1x1 struct with 1 field that is again A_x. Hence, I have not solved anything.
You can save the structure subfield name as a char and access the structure with it directly:
X=10;
C=cell(X,1)
for x=1:X
name = ['A_', num2str(x)];
data_structure = load([name, '.mat']); %here I load A_x.mat
C{x} = data_structure.(name) * 3;
end
Note that you could achieve something similar with eval() but that is not recommended. If ever you need to access variables dynamically like this, use a structure.
I am trying to loop through multiple structures at once, extract variables of interest, and combine them into a single cell array. The problem: all of the variables have the same names. I have a working pseudocode--here it is:
Let's say I load i structures in my workspace. Now I want to loop through each structure, and extract time and position data from each structure.
First, I load my structures. Something like...
data_1
data_2
data_3
Then, I create appropriately sized cell arrays.
time{i,:} = zeros(size(structures));
position{i,:} = zeros(size(structures));
Finally, I loop through my structures to extract cell arrays and create a single array.
for i = 1:size(structures)
time_i= data_i.numbers.time;
position_i= data_i.numbers.position;
time {i,:} = time_i;
position{i,:} = position_i;
end
I want to end with a cell array containing a concatenation of all the variables in a single cell structure.
Could you please help convert my pseudo code/ideas into a script, or point me to resources that might help?
Thanks!
You're likely going to be better off loading your data internal to the loop and storing it into a cell or structure rather than trying to deal with iteratively named variables in your workspace. eval is, in nearly all cases, a significant code smell, not least of which because MATLAB's JIT compiler ignores eval statements so you get none of the engine's optimizations. eval statements are also difficult to parse, debug, and maintain.
An example of a stronger approach:
for ii = 1:nfiles
tmp = load(thefilenames{ii}); % Or use output of dir
trialstr = sprintf('trial_%u', ii); % Generate trial string
data.(trialstr).time = tmp.numbers.time;
data.(trialstr).position = tmp.numbers.position;
end
Which leaves you with a final data structure of:
data
trial_n
time
position
Which is far easier to iterate through later.
My final script for anyone interested:
for i = 1:4 %for 4 structures that I am looping through
eval(['time_',num2str(i),'= data_',num2str(i),'.numbers.time;']);
eval(['position_',num2str(i),'= data_',num2str(i),'.numbers.position;']);
%concatenate data into a single cell array here
time{i} = {eval(['time_',num2str(i)])};
position{i} = {eval(['position_',num2str(i)])};
end
...
eval(['time_',num2str(i),'= data_',num2str(i),'.numbers.time;'])
eval(['position_',num2str(i),'= data_',num2str(i),'.numbers.position;'])
...
I am storing the field variables calculated in a for loop in a vector by appending the values, However I would like to preallocate first for performance. I tried to vectorize this operation but it does not give me what I would like to accomplish. I have put the example of the operation below. How do I do the preallocation in this? For speed.
j=('load raw.mat');
var=fields(j);
val_mat=[];
kk=fieldnames(j);
for i=(length(kk)-Var_no)+1:Var_no+(length(kk)-Var_no)
val_mat=[val_mat j.(var{i})];
end
Based on your code it looks like you are trying to grab all variables stored in raw.mat and concatenate them. To do this, you can replace the loop with struct2cell to convert all field values to a cell array of values and then use cat to concatenate them
data = load('raw.mat');
values = struct2cell(data);
val_mat = cat(2, values{:});
Since we have removed the loop, there is no need to pre-allocate.
I've also taken the liberty to rewrite your code as valid MATLAB code.
I want to create a loop that will iterate over several strings, but unable to do so in Matlab.
What works is:
for i=1:3
if (i==1)
b='cow';
elseif (i==2)
b='dog';
else
b='cat';
end
disp(b);
end
and the result is:
cow
dog
cat
But what I want is something more elegant that will look like:
for i=['cow','dog','cat']
disp (i);
end
and give the same result.
Is there an option in Matlab to do this?
ADDITION:
I need the words as strings later on to use and not just to display (the disp was just as an example). I've tried to use cell arrays in my real program:
clear all;
close all;
clc;
global fp_a
global TEST_TYPE
global SHADE_METHODE
for fp_a=11:24
for shade={'full','fast'}
SHADE_METHODE=shade(1);
for test={'bunny','city'}
TEST_MODE=test(1);
fprintf ('fp_a:%d | test: %s | shade: %s',fp_a,TEST_TYPE,SHADE_METHODE);
ray_tracing;
end
end
end
It doesn't work as the values stay as cells and not strings I get the error message:
??? Error using ==> fprintf Function is not defined for 'cell' inputs.
*-I don't really need the fprintf I just use it to check that the values are correct.
**-ray_tracing is my code that uses the values of the strings
Or you can do:
for i={'cow','dog','cat'}
disp(i{1})
end
Result:
cow
dog
cat
Your problems are probably caused by the way MATLAB handles strings. MATLAB strings are just arrays of characters. When you call ['cow','dog','cat'], you are forming 'cowdogcat' because [] concatenates arrays without any nesting. If you want nesting behaviour you can use cell arrays which are built using {}. for iterates over the columns of its right hand side. This means you can use the idiom you mentioned above; Oli provided a solution already. This idiom is also a good way to showcase the difference between normal and cell arrays.
%Cell array providing the correct solution
for word = {'cow','dog','cat'}
disp(word{1}) %word is bound to a 1x1 cell array. This extracts its contents.
end
cow
dog
cat
%Normal array providing weirdness
for word = ['cow','dog','cat'] %Same as word = 'cowdogcat'
disp(word) %No need to extract content
end
c
o
w
d
o
g
c
a
t
Sure! Use cell arrays for keeping strings (in normal arrays, strings are considered by character, which could work if all strings have the same length, but will bork otherwise).
opts={'cow','dog','cat'}
for i=1:length(opts)
disp(opts{i})
end
Use string arrays which where introduced in R2017a I believe. Note the double-quotes:
for i = ["cow", "dog", "cat"]
disp(i);
end
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.