The code segment I'm working on is given below:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
while i <= 10 %number of iterations
ind = randi([1 NphaseSteps],10,10);
inField{i} = phases(ind);
save('inField.mat', 'inField')
i = i + 1;
end
Now, what I want is to keep track of these randomly created matrices "inField{i}" and eliminate the ones that are equal to each other. I know that I can use "if" condition but since I'm new to programming I don't know how to use it more efficiently so that it doesn't take too much time. So, I need your help for a fast working program that does the job. Thanks in advance.
My actual code segment (after making the changes suggested by #bisherbas) is the following. Note that I actually want to use the variable "inField" inside the loop for every random created matrix and the loop advances only if the result satisfies a specific condition. So, I think the answer given by #bisherbas doesn't really eliminate the equal inField matrices before they are used in the calculation. This is, of course, my fault since I didn't declare that in the beginning.
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
nIterations = 5;
inField = cell(1,nIterations);
i = 1;
j = 1;
while i <= nIterations % number of iterations
ind = randi([1 NphaseSteps],TMsize,TMsize);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
j = j+1;
outField{i} = TM * inField{i};
outI = abs(outField{i}).^2;
targetIafter{i} = abs(outField{i}(focusX,focusY)).^2;
middleI = targetIafter{i} / 2;
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
if mod(j-1,10^6) == 0
fprintf('The number of random matrices tried is: %d million \n',(j-1)/10^6)
end
end
Additionally, I've written a seemingly long expression for my loop condition:
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
Here I want a maximum element at some point (focusX, focusY) in the outField matrix. So the first condition decides whether the focus point has the maximum element for the matrix. But I additionally want all other elements to be smaller than a specific number (middleI) and that's why the second part of the if condition is written. However, I'm not very comfortable with this second condition and I'm open to any helps.
Try this:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
inField = cell(1,NphaseSteps);
while i <= NphaseSteps %number of iterations
ind = randi([1 NphaseSteps],NphaseSteps,NphaseSteps);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
save('inField.mat', 'inField')
i = i + 1;
end
Read more on cellfun here:
https://www.mathworks.com/help/matlab/ref/cellfun.html
I am trying to change the value of z by +1 every 750th, 1500th, 2250th,...,etc loop and this is what I have written:
len = 1500000;
y = 750;
z = 1;
for i = 1:len
if (i == [y.*(1:2000)])
z = z + 1;
end
end
Why is the value of z not changing? Can someone tell me what's wrong with my if statement please?
MATLAB only considers an array to be true if all elements are true. So with that in mind, if we look at your conditional for your if statement
i == (y .* (1:2000))
What this returns is an array of 2000 values where they are either all false (in the case where i isn't a multiple of y) and all false except for one true value when it is. Even when there is one true, this still evaluates to false and your if statement will never be evaluated.
A better way to do this is to use mod to check if a given i is a multiple of y
if mod(i, y) == 0
z = z + 1;
end
However, if the only contents of your loop are what you have shown, then you can simply omit the iterations that you don't care about
for i = y:y:len
z = z + 1;
end
If you actually do want to compare the array as you showed though, you'd be best to compute y .* 1:2000 outside of the loop and then use ismember to see if i is in the array
tmp = y .* (1:2000);
for i = 1:len
if ismember(i, tmp)
z = z + 1;
end
end
I have an array A (I have written so as to make it similar to the matrix that I am using) :
%%%%%%%%%%%%% This is Matrix %%%%%%%%%%%%%%%%%%%%
a = 3; b = 240; c = 10; d = 30; e = 1;
mtx1 = a.*rand(30,1) + a;
mtx2 = round((b-c).*rand(30,1));
mtx3 = round((d-e).*rand(30,1));
mtx4 = -9999.*ones(30,1);
A = [mtx1 mtx2 mtx3 mtx4];
for i = 10:12
for ii = 17 :19
A(i,:)= -9999;
A(ii,:)= 999;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
I would calculate some statistical values, excluding from the calculation the values **-9999 and 999.
the statistical values must be calculated with respect to each column.
the columns represent respectively: the wind speed, direction, and
other parameters
I wrote a code but it is not correct
[nr,ncc]=size(A);
for i=1:ncc
B = A(:,i); %// Temp Vector
Oup=1; Odw=1; %// for Vector Control
while Oup>0 %// || Odw>0 % Oup>0 OR Odw>0 , Oup>0 && (AND) Odw>0
B=sort(B,'descend');
U = find(B<999 & B>-9999); % find for each column of the temp
%vector
Oup = length(U); % Calculates the length
B(U)=[]; % Delete values -9999 and 9999
end
% calculates parameters with the vector temp
count(i)=length(B);
med(i)=mean(B);
devst(i)=std(B);
mediana(i)=median(B);
vari(i)=var(B);
kurt(i)=kurtosis(B);
Asimm(i)=skewness(B);
Interv(i)=range(B);
Mass(i)=max(B);
Mini(i)=min(B);
if length(B)<nr
B(length(B)+1:nr)=nan;
end
C(:,i)=B(:); %//reconstruction of the original matrix
end
would you have any suggestions?
If your data set is in A, and you want to operate on it with a function f, just use logical indexing, i.e.:
f(A( ~(A==999 & A==-9999) )) =...
Alternatively, use find and linear indexing:
ind = find( ~(A==999 & A==-9999) );
f(A(ind)) = ....
The following code does what it should and works of one column.
%% Working loop
z = HongKongPrices(1:end,114);
zeros = false(size(z));
r = size(z,1);
c = size(z,2);
for i = 5:r
if z(i) == z(i-4) && z(i) == z(i-3)
zeros(i-3:i) = 1
end
end
z(zeros) = NaN
I am trying to execute the for-loop on a per column basis for HongKongPrices, however the following code fails (I am starting with three columns for time reasons).
%% Non workling loop
z = HongKongPrices(1:end,[80 85 115]);
zeros = false(size(z));
r = size(z,1);
c = size(z,2);
for k = 1:c
x = z(1:end,k)
for i = 5:r
if x(i) == x(i-4) && x(i) == x(i-3)
zeros(i-3:i) = 1
end
end
end
x(zeros) = NaN
You don't need the variable x at all. You can use logical indexing in you if statement. Instead of x(i), use x(i,k) and so on. Of course you have to do the same with zeros.
z = HongKongPrices(1:end,[80 85 115]);
zeros = false(size(z));
r = size(z,1);
c = size(z,2);
for k = 1:c
for i = 5:r
if z(i,k) == z(i-4,k) && z(i,k) == z(i-3,k);
zeros(i-3:i,k) = 1
end
end
end
z(zeros) = NaN;
PS: zeros is a Matlab function, so it would be better to use another variable name. Like this you won't be able to use the zeros function in your code.
I have a matrix named l having size 20X3.
What I wanted to do was this :
Suppose I have this limits:
l1_max=20; l1_min=0.5;
l2_max=20; l2_min=0.5;
mu_max=20; mu_min=0.5;
I wanted to force all the elements of the matrix l within the limits.
The values of 1st column within l1_max & l1_min.
The values of 2nd column within l2_max & l2_min.
The values of 3rd column within mu_max & mu_min.
What I did was like this:
for k=1:20
if l(k,1)>l1_max
l(k,1) = l1_max;
elseif l(k,1)<l1_min
l(k,1) = l1_min;
end
if l(k,2)>l2_max
l(k,2) = l2_max;
elseif l(k,2)<l2_min
l(k,2) = l2_min;
end
if l(k,3)>mu_max
l(k,3) = mu_max;
elseif l(k,3)<mu_min
l(k,3) = mu_min;
end
end
Can it be done in a better way ?
You don't have to loop over rows, use vectorized operations on entire columns:
l(l(:, 1) > l1_max, 1) = l1_max;
l(l(:, 1) < l1_min, 1) = l1_min;
Similarily:
l(l(:, 2) > l2_max, 2) = l2_max;
l(l(:, 2) < l2_min, 2) = l2_min;
l(l(:, 3) > l2_max, 3) = mu_max;
l(l(:, 3) < l2_min, 3) = mu_min;
An alternative method, which resembles to Bas' idea, is to apply min and max as follows:
l(:, 1) = max(min(l(:, 1), l1_max), l1_min);
l(:, 2) = max(min(l(:, 2), l2_max), l2_min);
l(:, 3) = max(min(l(:, 3), mu_max), mu_min);
It appears that both approaches have comparable performance.
You don't even have to loop over all columns, the operation on the whole matrix can be done in 2 calls to bsxfun, independent of the number of columns:
column_max = [l1_max, l2_max, mu_max];
column_min = [l1_min, l2_min, mu_min];
M = bsxfun(#min, M, column_max); %clip to maximum
M = bsxfun(#max, M, column_min); %clip to minimum
This uses two tricks: to clip a value between min_val and max_val, you can do clipped_x = min(max(x, min_val), max_val). The other trick is to use the somewhat obscure bsxfun, which applies a function after doing singleton expansion. When you use it on two matrices, it 'extrudes' the smallest one to the same size as the largest one before applying the function, so the example above is equivalent to M = min(M, repmat(column_max, size(M, 1), 1)), but hopefully calculated in a more efficient way.
Below is a benchmark to test the various methods discussed so far. I'm using the TIMEIT function found on the File Exchange.
function [t,v] = testClampColumns()
% data and limits ranges for each column
r = 10000; c = 500;
M = randn(r,c);
mn = -1.1 * ones(1,c);
mx = +1.1 * ones(1,c);
% functions
f = { ...
#() clamp1(M,mn,mx) ;
#() clamp2(M,mn,mx) ;
#() clamp3(M,mn,mx) ;
#() clamp4(M,mn,mx) ;
#() clamp5(M,mn,mx) ;
};
% timeit and check results
t = cellfun(#timeit, f, 'UniformOutput',true);
v = cellfun(#feval, f, 'UniformOutput',false);
assert(isequal(v{:}))
end
Given the following implementations:
1) loop over all values and compare against min/max
function M = clamp1(M, mn, mx)
for j=1:size(M,2)
for i=1:size(M,1)
if M(i,j) > mx(j)
M(i,j) = mx(j);
elseif M(i,j) < mn(j)
M(i,j) = mn(j);
end
end
end
end
2) compare each column against min/max
function M = clamp2(M, mn, mx)
for j=1:size(M,2)
M(M(:,j) < mn(j), j) = mn(j);
M(M(:,j) > mx(j), j) = mx(j);
end
end
3) truncate each columns to limits
function M = clamp3(M, mn, mx)
for j=1:size(M,2)
M(:,j) = min(max(M(:,j), mn(j)), mx(j));
end
end
4) vectorized version of truncation in (3)
function M = clamp4(M, mn, mx)
M = bsxfun(#min, bsxfun(#max, M, mn), mx);
end
5) absolute value comparison: -a < x < a <==> |x| < a
(Note: this is not applicable to your case, since it requires a symmetric limits range. I only included this for completeness. Besides it turns out to be the slowest method.)
function M = clamp5(M, mn, mx)
assert(isequal(-mn,mx), 'Only works when -mn==mx')
idx = bsxfun(#gt, abs(M), mx);
v = bsxfun(#times, sign(M), mx);
M(idx) = v(idx);
end
The timing I get on my machine with an input matrix of size 10000x500:
>> t = testClampColumns
t =
0.2424
0.1267
0.0569
0.0409
0.2868
I would say that all the above methods are acceptably fast enough, with the bsxfun solution being the fastest :)