Say, I want to create 3 variables of same size in MATLAB:
a = zeros(3,3);
b = zeros(3,3);
c = zeros(3,3);
Is there any fast way to do this, I know this is not working but I think of something like
a,b,c = zeros(3,3);
Any suggestions?
To use deal there is no need to wrap it in a cell as NKN suggested:
[a,b,c]=deal(zeros(3,3))
Although you can do this:
a = zeros(3); % a 3x3 zero matrix
b = a;
c = a;
If you define the values that you want to assign, in a cell, the other way (faster) is:
c={zeros(3)};
[a1,a2,a3,a4]=deal(c{1})
it means that you put your assigning value in a cell and then use deal function. Notice that the a1,a2,a3,a4 does not have cell formats, but double formats and actually this is a very fast method.
If you use cell foramt you can assign more values at the same time, for example:
C = {rand(3) ones(3,1) eye(3) zeros(3,1)};
[a,b,c,d] = deal(C{:})
otherwise you can just get rid of the cell and use:
c=zeros(3);
[a1,a2,a3,a4]=deal(c);
as Daniel Suggested.
Related
Here is my code:
A = zeros(10,10,10);
for i = 1:10
C{i} = A(:,:,i);
end
This is just a simple example and my question is: Is there any other way, NOT using a cell (C{i} in the code) to represent a series of 2D matrices variables (A(:,:,i) in the code) from a 3D matrix (A). Anyway I believe you will need some variable name like 'i'.
Thanks in advance!
You can do:
A = zeros(10,10,10);
for i = 1:10
eval(sprintf('A%d = A(:,:,%d)',i,i));
end
In this way you get 10 matrices whose names are A1, A2, ..., Ai,...
Anyway I suggest not using this method. It is more readable the one with cell arrays.
I would like to name variable (type double) in the following way:
k0 = D(1,1);
k1 = D(2,2);
k2 = D(3,3);
k3 = D(4,4);
k4 = D(5,5);
k5 = D(6,6);
k6 = D(7,7);
k7 = D(8,8);
...
up to k99 automatically using for loop. So I see that I should use array or cell instead of double variable using eval as it is slow. But if I should use array or cell instead of double variable, I have to start at k{1} or k(1), which loses the meaning as I want exactly that k0 refers to D(1,1), i.e. the number in my variable is 1 less. How do I create meaningful cell name like k{0}?
Also, say I have an array A. There are also some times i need meaningful variable name, such as
c111 = A(1)*A(1)*A(1)
c222 = A(2)*A(2)*A(2)
c333 = A(3)*A(3)*A(3)
How can I create c{111} efficiently using for loop?
Use structures:
D = rand(21);
c = 1;
for k = -10:10
if k<0
s.(['k_' num2str(abs(k))]) = D(c,c);
else
s.(['k' num2str(k)]) = D(c,c);
end
c = c+1;
end
This will give you a structure like:
s =
k_10: 0.51785
k_9: 0.90121
k_8: 0.40746
k_7: 0.092989
.
.
k_1: 0.75522
k0: 0.55257
k1: 0.28708
.
.
k9: 0.94182
k10: 0.2124
and don't use eval...
Answer to 1st Question:-
D=randn(100); % A matrix of random elements of size 8x8
for m=0:99
assignin('base', ['k' num2str(m)], D(m+1,m+1))
end
Answer to 2nd Question:-
A=randn(1,3); % An array of 3 random elements
for n=1:3
assignin('base', ['c' num2str(111*n)], A(n)^3)
end
Comments:-
You've stated that you need variables like k0,k1,k2,... and c111,c222,c333 but you're asking how to create k{0}, k{1},k{2},... and c{111},c{222},c{333}. As far as your need is concerned, I have given answer to it. Regarding the latter, k{0} is never possible and c{111},c{222},c{333},... don't make good sense without using any of the first 0:100 values and then 112:221 values and so on. Although you can do it using:
A=rand(1,3); % An array of 3 random elements
c{333} = 0 ; % Pre-allocation
for p=1:3 % Since you want to use a 'for loop'
c{111*p} = A(p)^3;
end
And regarding the requirement that you made in the comment in these words "I also have some variable using negative index", you can never have variables in the negative index. If you mean you want to create variables with names like k-1, k-2,... etc, it is not possible. An alternate way is to use k_1, k_2,... etc but then as you said in the question "k0 refers to D(1,1), i.e. the number in my variable is 1 less". It means k_1 will refer to D(0,0) and so on which is again an invalid thing for MATLAB.
Recommendation:-
You really need to modify your code.
Given the code below:
% Generate some random data
n = 10;
A = cell(n, 1);
for i=1:n
A{i} = timeseries;
A{i}.Data = rand(100, 1);
A{i}.Time = 1:100;
end
I would like to make the sum of Data(end) without explicitly writing a for loop. Is there a smart way to select Data(end) in all cells in a single line? A{:}.Data(end) does not work.
You can do it with cellfun but that is essentially just a for loop wrapped up:
cellfun(#(x) x.Data(end), A)
I prefer Dan's answer, but for reference, I'll post an alternative using arrayfun. This is also just a for loop wrapped up to save keystrokes, but not necessarily time.
sum(arrayfun(#(n) A{n}.Data(end), 1:numel(A)))
You can also extract all of the Data fields into a single matrix, which might be worth it if you're planning on doing multiple operations on it:
A2 = [A{:}];
A3 = [A2.Data];
sum(A3(end,:))
How would I generate a vector like
x1,x2,x3,x4,...,xn
the problem is concatenate ','and a 'x' char
n=100
A = (1:n);
This is a slight improvement on #Jonas's answer. SPRINTF will do the repeating for you avoiding the need for a mask:
>> n = 5;
>> out = sprintf('x%u,', 1:n);
>> out(end) = []
out =
x1,x2,x3,x4,x5
To generate the string 'x1,x2' etc, you can create a mask for SPRINTF using REPMAT like so:
n = 5;
mask = repmat('x%i,',1,n);
out = sprintf(mask,1:n);
out = out(1:end-1)
out =
x1,x2,x3,x4,x5
Note that in case you actually want to create a vector containing the strings 'x1','x2' etc, you'd use ARRAYFUN to generate a cell array:
out = arrayfun(#(x)sprintf('x%i',x),1:n,'uniformOutput',false)
out =
'x1' 'x2' 'x3' 'x4' 'x5'
The better answer is, don't do it. While you CAN do so, this will likely cause more heartache for you in the future than you want. Having hundreds of such variables floating around is silly, when you can use an array to index the same data. Thus perhaps x{1}, x{2}, ....
I need to calculate the mean, standard deviation, and other values for a number of variables and I was wondering how to use a loop to my advantage. I have 5 electrodes of data. So to calculate the mean of each I do this:
mean_ch1 = mean(ch1);
mean_ch2 = mean(ch2);
mean_ch3 = mean(ch3);
mean_ch4 = mean(ch4);
mean_ch5 = mean(ch5);
What I want is to be able to condense that code into a line or so. The code I tried does not work:
for i = 1:5
mean_ch(i) = mean(ch(i));
end
I know this code is wrong but it conveys the idea of what I'm trying to accomplish. I want to end up with 5 separate variables that are named by the loop or a cell array with all 5 variables within it allowing for easy recall. I know there must be a way to write this code I'm just not sure how to accomplish it.
You have a few options for how you can do this:
You can put all your channel data into one large matrix first, then compute the mean of the rows or columns using the function MEAN. For example, if each chX variable is an N-by-1 array, you can do the following:
chArray = [ch1 ch2 ch3 ch4 ch5]; %# Make an N-by-5 matrix
meanArray = mean(chArray); %# Take the mean of each column
You can put all your channel data into a cell array first, then compute the mean of each cell using the function CELLFUN:
meanArray = cellfun(#mean,{ch1,ch2,ch3,ch4,ch5});
This would work even if each chX array is a different length from one another.
You can use EVAL to generate the separate variables for each channel mean:
for iChannel = 1:5
varName = ['ch' int2str(iChannel)]; %# Create the name string
eval(['mean_' varName ' = mean(' varName ');']);
end
If it's always exactly 5 channels, you can do
ch = {ch1, ch2, ch3, ch4, ch5}
for j = 1:5
mean_ch(j) = mean(ch{j});
end
A more complicated way would be
for j = 1:nchannels
mean_ch(j) = eval(['mean(ch' num2str(j) ')']);
end
Apart from gnovice's answer. You could use structures and dynamic field names to accomplish your task. First I assume that your channel data variables are all in the format ch* and are the only variables in your MATLAB workspace. The you could do something like the following
%# Move the channel data into a structure with fields ch1, ch2, ....
%# This could be done by saving and reloading the workspace
save('channelData.mat','ch*');
chanData = load('channelData.mat');
%# Next you can then loop through the structure calculating the mean for each channel
flds = fieldnames(chanData); %# get the fieldnames stored in the structure
for i=1:length(flds)
mean_ch(i) = mean(chanData.(flds{i});
end