Compress variable assignment into for loop in matlab [duplicate] - matlab

This question already has an answer here:
How to put these images together?
(1 answer)
Closed 4 years ago.
I want to compress part of my code into a for loop. The code looks like this:
dataMixSp1 = [dataSp1{1}; dataSp1{2}; dataSp1{3}; dataSp1{4};];
dataMixSp2 = [dataSp2{1}; dataSp2{2}; dataSp2{3}; dataSp2{4};];
dataMixSp3 = [dataSp3{1}; dataSp3{2}; dataSp3{3}; dataSp3{4};];
dataMixSp4 = [dataSp4{1}; dataSp4{2}; dataSp4{3}; dataSp4{4};];
dataMixSp5 = [dataSp5{1}; dataSp5{2}; dataSp5{3}; dataSp5{4};];
dataMixSp6 = [dataSp6{1}; dataSp6{2}; dataSp6{3}; dataSp6{4};];
dataMixSp7 = [dataSp7{1}; dataSp7{2}; dataSp7{3}; dataSp7{4};];
dataMixSp8 = [dataSp8{1}; dataSp8{2}; dataSp8{3}; dataSp8{4};];
dataMixSp9 = [dataSp9{1}; dataSp9{2}; dataSp9{3}; dataSp9{4};];
dataMixSp10 = [dataSp10{1}; dataSp10{2}; dataSp10{3}; dataSp10{4};];
The problem is that I don't know how to dynamically create variables inside the for loop.
I tried this but it is not working:
a = 'dataMixSp';
for idx = 1:10
[a num2str(idx)] = [['dataSp', num2str(idx), '{1}']; ['dataSp' num2str(idx) '{2}']; ['dataSp' num2str(idx) '{3}']; ['dataSp' num2str(idx) '{4}']; ];
end

To have Matlab evaluate an instruction in a string, use the eval function. For the problem you show, this could be done as:
root = 'dataMix';
part = 'dataSp';
for k=1:10
target = sprintf('%s%d', root,k); % creates strings 'dataMix1', 'dataMix2', ...
thisPart = sprintf('%s%d', part,k); %creates strings 'dataSp1, 'dataSp2', ...
rhs = '['; % the opening of the right-hand-side of the assignment
for n=1:4
rhs=sprintf('%s%s{%d};',rhs,thisPart,n);%appends 'dataSp1{1}, dataSp1{2}...
end
rhs=strcat(rhs(1:end-1),']');% close the right-hand-side
% note the (1:end-1) to remove the ';' between the last variable and the ']'
instruction = sprintf('%s = %s;',target,rhs); % create a Matlab instuction
eval(instruction) % have Matlab evaluate the instruction
end
Although, as #tryman said, sometimes the problem is easier to solve saving the data in a different way.
Hope this helps
JAC

for idx = 1:10
eval( [ 'dataMixSp' num2str(idx) '= [ dataSp' num2str(idx), '{1}; dataSp' num2str(idx) '{2}; dataSp' num2str(idx) '{3}; dataSp' num2str(idx) '{4} ];' ] )
end
Will execute the following code:
dataMixSp1= [ dataSp1{1}; dataSp1{2}; dataSp1{3}; dataSp1{4} ];
dataMixSp2= [ dataSp2{1}; dataSp2{2}; dataSp2{3}; dataSp2{4} ];
dataMixSp3= [ dataSp3{1}; dataSp3{2}; dataSp3{3}; dataSp3{4} ];
dataMixSp4= [ dataSp4{1}; dataSp4{2}; dataSp4{3}; dataSp4{4} ];
dataMixSp5= [ dataSp5{1}; dataSp5{2}; dataSp5{3}; dataSp5{4} ];
dataMixSp6= [ dataSp6{1}; dataSp6{2}; dataSp6{3}; dataSp6{4} ];
dataMixSp7= [ dataSp7{1}; dataSp7{2}; dataSp7{3}; dataSp7{4} ];
dataMixSp8= [ dataSp8{1}; dataSp8{2}; dataSp8{3}; dataSp8{4} ];
dataMixSp9= [ dataSp9{1}; dataSp9{2}; dataSp9{3}; dataSp9{4} ];
dataMixSp10= [ dataSp10{1}; dataSp10{2}; dataSp10{3}; dataSp10{4} ];
Arno

Related

Looking for a more efficient way of writing my MATLAB code

I have written in MATLAB the following
for i = 1:3
alpha11(i) = b+a.*randn(1,1);
alpha22(i) = b+a.*randn(1,1);
alpha12(i) = b+a.*randn(1,1);
alpha21(i) = b+a.*randn(1,1);
AoD11(i) = randi([-180/6 +180/6],1,1);
AoA11(i) = randi([-180/6 +180/6 ],1,1);
AoD22(i) = randi([-180/6 +180/6],1,1);
AoA22(i) = randi([-180/6 +180/6 ],1,1);
AoD21(i) = randi([-180 +180],1,1);
AoA21(i) = randi([-180 +180 ],1,1);
AoD12(i) = randi([-180 +180],1,1);
AoA12(i) = randi([-180 +180 ],1,1);
ctet11(i)= ((2*pi)/lambda)*d*sin(AoD11(i));
ctet22(i)= ((2*pi)/lambda)*d*sin(AoD22(i));
ctet12(i)= ((2*pi)/lambda)*d*sin(AoD12(i));
ctet21(i)= ((2*pi)/lambda)*d*sin(AoD21(i));
f_t11_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet11(i)) exp(j*2*ctet11(i)) exp(j*3*ctet11(i)) ]);
f_t22_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet22(i)) exp(j*2*ctet22(i)) exp(j*3*ctet22(i)) ]);
f_t12_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet12(i)) exp(j*2*ctet12(i)) exp(j*3*ctet12(i)) ]);
f_t21_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet21(i)) exp(j*2*ctet21(i)) exp(j*3*ctet21(i)) ]);
cter11(i)= ((2*pi)/lambda)*d*sin(AoA11(i));
cter22(i)= ((2*pi)/lambda)*d*sin(AoA22(i));
cter12(i)= ((2*pi)/lambda)*d*sin(AoA12(i));
cter21(i)= ((2*pi)/lambda)*d*sin(AoA21(i));
f_r11_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter11(i)) exp(j*2*cter11(i)) exp(j*3*cter11(i)) ]);
f_r22_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter22(i)) exp(j*2*cter22(i)) exp(j*3*cter22(i))]);
f_r12_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter12(i)) exp(j*2*cter12(i)) exp(j*3*cter12(i)) ]);
f_r21_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter21(i)) exp(j*2*cter21(i)) exp(j*3*cter21(i))]);
channel11{i}= alpha11(i) * f_r11_ula{i}* conj(transpose(f_t11_ula{i})) ;
channel22{i}= alpha22(i) * f_r22_ula{i}* conj(transpose(f_t22_ula{i})) ;
channel12{i}= alpha12(i) * f_r12_ula{i}* conj(transpose(f_t12_ula{i})) ;
channel21{i}= alpha21(i) * f_r21_ula{i}* conj(transpose(f_t21_ula{i})) ;
end
I am writing this question here to ask how I can compress this code, as you can see its not very nicely written and I have basically many repetitions. I don't know how to write them in few commands. Every command is repeated four times and indexed by 11, 12, 21, 22..
P.S If someone wants to run the code the following variables are needed
a = 1;
b = 0;
M=4;
O = 4;
lambda=0.15;
d=lambda/2;
Looking forward for suggestions.
As #David mentioned, it can be done using 3D arrays. This removes much of the code repetition.
Here is an example of how it could be done:
sz=[2,2,3];
alpha=b+a.*randn(sz);
AoD = randi([-180/6 +180/6],sz);
AoA = randi([-180 +180],sz);
mask = logical(repmat(eye(2),1,1,3));
[AoA(mask), AoD(~mask)] = deal(AoD(~mask),AoA(mask));
ctet = 2*pi/lambda * d * sin(AoD);
f_t = reshape(arrayfun(#(x) exp(1j*(0:3)'*ctet(x))/sqrt(M),1:12,'UniformOutput',0),sz);
cter = (2*pi)/lambda*d*sin(AoA);
f_r = reshape(arrayfun(#(x) exp(1j*(0:3)'*cter(x))/sqrt(O),1:12,'UniformOutput',0),sz);
channel = reshape(arrayfun(#(x) alpha(x) * f_r{x} * conj(transpose(f_t{x})), 1:12, 'UniformOutput',0),sz);
Note that for each of the variables mentioned in the question, the same values can be accessed using the corresponding 3D index. For example, using the code above, the value that was previously in AoA11(1) is now in AoA(1,1,1). Similarly, the matrix that was stored in channel11{1} is now in channel{1,1,1}.
Hope this helps.

Matlab) what should I put more with function for, sttrep, cell?

I want to make the results like this:
phraseblanks
phrasemat = Hello and how are you?
Hi there everyone!
How is it going?
WHazzup?
Phrase 1 had 4 blanks
Phrase 2 had 3 blanks
Phrase 3 had 2 blanks
Phrase 4 had 0 blanks
New phrasemat is :
Hello&and&how&are&you?
Hi&there&everyone!
How&is&it&going?
WHazzup?
so I made script "phraseblanks.m":
phrasemat = char('Hello and how are you?', ...
'Hi there everyone!', 'How is it going?', 'WHazzup?')
[r, c] = size(phrasemat);
for i = 1:r
phrasemat_new = cell(r, c);
howmany = countblanks(phrasemat(i, :));
fprintf('Phrase %d had %d blanks\n', i, howmany);
phrasemat(i,:) = strrep(phrasemat(i,:),' ','&')
phrasemat_new{i,:} = [phrasemat(i,:)];
end
fprintf('Changing one is %s\n', eval('phrasemat_new'));
script "countblanks.m":
function num = countblanks(phrase)
% countblanks returns the # of blanks in a trimmed string
% Format: countblanks(string)
num = length(strfind(strtrim(phrase), ' '));
end
and I keep having errors.
please help me..
I modified slightly your phraseblanks.m so that it works.
phrasemat = {'Hello and how are you?', ...
'Hi there everyone!', ...
'How is it going?', ...
'WHazzup?'};
r = numel(phrasemat);
phrasemat_new = cell(1, r);
for i = 1:r
howmany = countblanks(phrasemat{i});
fprintf('Phrase %d had %d blanks\n', i, howmany);
phrasemat{i} = strrep(phrasemat{i}, ' ', '&');
phrasemat_new(i) = phrasemat(i);
end
fprintf('Changing one is %s\n', phrasemat_new{:});
Obviously it could be written in a nicer, more "matlaby-way", but I didn't want to stride too far from your original version. Also you could consider using regular expressions, since if you have to spaces next to each other and you want to treat them as one blank space.

Error in Matlab, calling a function

The errors are:
Error in getvalues (line 4)
faceNoNoise = wiener2(x, [5 5]);
Output argument "mouthTall" (and maybe others) not assigned during call to "C:\Users\Trent\face\getvalues.m>getvalues".
Error in finalProject2 (line 10)
[ numWhiteEyebrow, mouthTall, eyebrowHeight ] = getvalues( faceGray )
faceNoNoise = wiener2(x, [5 5]); <---- getvalues.m line with error
function finalProject2(x) <----- finalproject file
face = imread(x);
faceGray = rgb2gray(face);
numWhiteEyebrow = 0;
mouthTall = 0;
eyebrowHeight = 0;
[ numWhiteEyebrow, mouthTall, eyebrowHeight ] = getvalues( faceGray ) <--error above
end
Im trying to figure out why its doing this...
This happens since you have not assigned required output values in the function getvalues.m. There are 3 output arguments which should be returned by getvalues.m. See this and this. To clarify even more, if your function definition in getvalues.m file is [a,b,c]=getvalues(x) (and this is how it would mostly be in your case) then in your getvalue.m file, you should have variables a, b and c.

nested for loop query

I am trying to do something rather simple, but can't seem to get it...
I have 3 cell-arrays with strings,
A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage';...
'Sugar'}
I want to produce a vector with the concatenated (strcat?) combinations, as it this were a "tree diagram", like:
strcat(A(1),B(1),C(1))
strcat(A(1),B(1),C(2))
strcat(A(1),B(1),C(3))
strcat(A(1),B(1),C(4))
strcat(A(1),B(1),C(5))
strcat(A(1),B(1),C(6))
strcat(A(1),B(1),C(7))
strcat(A(1),B(2),C(1))
So what the first elements I am trying to get are (in a column ideally):
ConditionACase1Rice
ConditionACase1Beans
ConditionACase1Carrots
ConditionACase1Cereal
ConditionACase1Tomato
ConditionACase1Cabbage
ConditionACase1Sugar
ConditionACase2Rice
etc etc etc...
I know that:
for i=1:length(A)
E(i) = strcat(A(i),B(1),C(1))
end
Works for one "level". I have tried:
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(i) = strcat(A(i),B(j),C(k));
end
end
end
But this doesn't work...
I would be really grateful if I could be helped with this.
Thanks in advance!
From what I understood, you want all possible combinations of the strings of the input arrays as specified. If so, simply replace your nested loops with the following:
P = cell(length(A)*length(B)*length(C),1);
t=1;
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(t) = strcat(A(i),B(j),C(k));
t = t+1;
end
end
end
For the input arrays,
>> A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
>> B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
>> C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage';'Sugar'};
The value of P would be:
>> P
P =
'ConditionACase1Rice'
'ConditionACase1Beans'
'ConditionACase1Carrots'
'ConditionACase1Cereal'
'ConditionACase1Tomato'
'ConditionACase1Cabbage'
'ConditionACase1Sugar'
'ConditionACase2Rice'
'ConditionACase2Beans'
'ConditionACase2Carrots'
'ConditionACase2Cereal'
'ConditionACase2Tomato'
'ConditionACase2Cabbage'
'ConditionACase2Sugar'
'ConditionACase3Rice'
'ConditionACase3Beans'
'ConditionACase3Carrots'
'ConditionACase3Cereal'
'ConditionACase3Tomato'
'ConditionACase3Cabbage'
'ConditionACase3Sugar'
'ConditionACase4Rice'
'ConditionACase4Beans'
'ConditionACase4Carrots'
'ConditionACase4Cereal'
'ConditionACase4Tomato'
'ConditionACase4Cabbage'
'ConditionACase4Sugar'
'ConditionBCase1Rice'
'ConditionBCase1Beans'
'ConditionBCase1Carrots'
'ConditionBCase1Cereal'
'ConditionBCase1Tomato'
'ConditionBCase1Cabbage'
'ConditionBCase1Sugar'
'ConditionBCase2Rice'
'ConditionBCase2Beans'
'ConditionBCase2Carrots'
'ConditionBCase2Cereal'
'ConditionBCase2Tomato'
'ConditionBCase2Cabbage'
'ConditionBCase2Sugar'
'ConditionBCase3Rice'
'ConditionBCase3Beans'
'ConditionBCase3Carrots'
'ConditionBCase3Cereal'
'ConditionBCase3Tomato'
'ConditionBCase3Cabbage'
'ConditionBCase3Sugar'
'ConditionBCase4Rice'
'ConditionBCase4Beans'
'ConditionBCase4Carrots'
'ConditionBCase4Cereal'
'ConditionBCase4Tomato'
'ConditionBCase4Cabbage'
'ConditionBCase4Sugar'
'ConditionCCase1Rice'
'ConditionCCase1Beans'
'ConditionCCase1Carrots'
'ConditionCCase1Cereal'
'ConditionCCase1Tomato'
'ConditionCCase1Cabbage'
'ConditionCCase1Sugar'
'ConditionCCase2Rice'
'ConditionCCase2Beans'
'ConditionCCase2Carrots'
'ConditionCCase2Cereal'
'ConditionCCase2Tomato'
'ConditionCCase2Cabbage'
'ConditionCCase2Sugar'
'ConditionCCase3Rice'
'ConditionCCase3Beans'
'ConditionCCase3Carrots'
'ConditionCCase3Cereal'
'ConditionCCase3Tomato'
'ConditionCCase3Cabbage'
'ConditionCCase3Sugar'
'ConditionCCase4Rice'
'ConditionCCase4Beans'
'ConditionCCase4Carrots'
'ConditionCCase4Cereal'
'ConditionCCase4Tomato'
'ConditionCCase4Cabbage'
'ConditionCCase4Sugar'
'ConditionDCase1Rice'
'ConditionDCase1Beans'
'ConditionDCase1Carrots'
'ConditionDCase1Cereal'
'ConditionDCase1Tomato'
'ConditionDCase1Cabbage'
'ConditionDCase1Sugar'
'ConditionDCase2Rice'
'ConditionDCase2Beans'
'ConditionDCase2Carrots'
'ConditionDCase2Cereal'
'ConditionDCase2Tomato'
'ConditionDCase2Cabbage'
'ConditionDCase2Sugar'
'ConditionDCase3Rice'
'ConditionDCase3Beans'
'ConditionDCase3Carrots'
'ConditionDCase3Cereal'
'ConditionDCase3Tomato'
'ConditionDCase3Cabbage'
'ConditionDCase3Sugar'
'ConditionDCase4Rice'
'ConditionDCase4Beans'
'ConditionDCase4Carrots'
'ConditionDCase4Cereal'
'ConditionDCase4Tomato'
'ConditionDCase4Cabbage'
'ConditionDCase4Sugar'
Let me know if you need further assistance.
I am not really familiar with matlab.. but maybe try something like this?
for A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
for B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
for C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage'; 'Sugar'}
P(i) = strcat(A(i),B(j),C(k));
end
end
end
{
x = 1;
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(x) = strcat(A(i),B(j),C(k));
x = x + 1;
end
end
end
}
Please basically check your code before posting to PO as this is a very simple debugging

How can I load 100 files with similar names and/or string in just one step in MATLAB?

I have 100 ASCII files in my directory all named as follows:
int_001.ASC
int_002.ASC
int_003.ASC
.
.
.
int_099.ASC
int_100.ASC
I have to import them in MATLAB all with importdata, which should work as follows:
A = importdata('int_001.ASC', ' ', 9)
x = A.data(:,1)
y = A.data(:,2)
My question is: how can I avoid writing 100 times importdata? Is there a way to write the first string only and then have all data uploaded?
Thanks
fls = dir( 'int_*.ASC' );
for fi=1:numel(fls)
A{fi} = importdata( fls(fi).name, ' ', 9 );
% ...
end
UPDATE:
You may use string formatting to read the files according to their numbers:
for fi=1:100
A{fi} = importdata( sprintf('int_%03d.ASC', fi ), ' ', 9 );
% ...
end
You can use strcat function in a for loop :
for k=1:n
fileName = strcat('int_',num2str(k, '%03d'),'.ASC');
A(k) = importdata(fileName, ' ', 9);
x(k) = A(k).data(:,1);
y(k) = A(k).data(:,2);
end
If you want to take this a little overboard:
alldata = arrayfun(...
#(dirEntry)importdata(dirEntry.name, ' ', 9), ...
dir('int_*.ASC'),...
'uniformoutput',false);
This line does the following
Gets a listing of all files matching the partial filename, as an array of structures (h/t Shai)
For each element in that array, performs the importdata call from your original post.
Compiles all the outputs into a cell array.