Double loop for each column per row in matlab - matlab

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.

Related

if statement to skip certain values in loop

I have a range of X and Y values, and I have a domain that I don't want to calculate the values of nodes within. I want to have an if statement within a loop in Matlab to skip these.
For example:
Range: X = [1:20] and Y = [1:20].
I want to ignore nodes in this range: X = [5:7] and Y = [12:14].
I think the code should be something like this:
for X=1:20
for Y=1:20
if X=5:7 & Y=12:14
return
end
% the operation here !
T(X,Y) = lab lab lab
end
end
However, I'm not sure how to properly write the condition.
You could use ismember or a combination of any and == for the condition, and continue is the command for skipping to the next loop index...
% ismember example
for X = 1:20
for Y = 1:20
if ismember( X, 5:7 ) && ismember( Y, 12:14 )
continue
end
% your loop operations
end
end
In this case, you could replace the if condition with
if any( X == 5:7 ) && any( Y == 12:14 )
I propose an alternative to Wolfie's solution to generate all indices in advance, and then apply a single loop:
Xvect = repmat(X, length(Y), 1);
Yvect = repmat(Y, 1, length(X));
Xvect = Xvect(:);
Yvect = Yvect(:);
Xis5to7 = (Xvect >= 5) & (Xvect <= 7);
Yis12to14 = (Yvect >= 12) & (Yvect <= 14);
XYcomb = ~(Xis5to7 & Yis12to14); % This is the range to exclude, negate it.
allX = Xvect(XYcomb);
allY = Yvect(XYcomb);
(par)for i = 1 : length(allX);
X = allX(i);
Y = allY(i);
Ltemp(i) = ...;
end
L(XYcomb) = Ltemp;
The advantage is to have combinations (allX, allY) displayed up front plus due to a single loop it is very suitable to make a parfor out of it.

Exclude value by the calculation

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)) = ....

Storing non-zero integers from one matrix into another

I'm attempting to create a loop that reads through a matrix (A) and stores the non-zero values into a new matrix (w). I'm not sure what is wrong with my code.
function [d,w] = matrix_check(A)
[nrow ncol] = size(A);
total = 0;
for i = 1:nrow
for j = 1:ncol
if A(i,j) ~= 0
total = total + 1;
end
end
end
d = total;
w = [];
for i = 1:nrow
for j = 1:ncol
if A(i,j) ~= 0
w = [A(i,j);w];
end
end
end
The second loop is not working (at at least it is not printing out the results of w).
You can use nonzeros and nnz:
w = flipud(nonzeros(A)); %// flipud to achieve the same order as in your code
d = nnz(A);
The second loop is working. I'm guessing you're doing:
>> matrix_check(A)
And not:
>> [d, w] = matrix_check(A)
MATLAB will only return the first output unless otherwise specified.
As an aside, you can accomplish your task utilizing MATLAB's logical indexing and take advantage of the (much faster, usually) array operations rather than loops.
d = sum(sum(A ~= 0));
w = A(A ~= 0);

Have to convert Integer to binary

I'm writing a user-defined function to convert integers to binary. The largest number that could be converted with the function should be a binary number with
16 1 s. If a larger number is entered as d, the function should display an error
message. With my code, I'm trying to add the numbers 0 or 1 to my vector x based on the remainder, then I want to reverse my final vector to display a number in binary. Here's what I have:
function [b] = bina(d)
% Bina is a function that converts integers to binary
x = [];
y = 2;
in = d/2;
if d >=(2^16 -1)
fprintf('This number is too big')
else
while in > 1
if in >= 1
r = rem(in,y);
x = [x r]
end
end
end
end
As you insist on a loop:
x = [];
y = 2;
in = d;
if d >=(2^16 -1)
fprintf('This number is too big')
else
ii = 1;
while in > 0
r = logical(rem(in,y^ii));
x = [r x];
in = in - r*2^(ii-1);
ii = ii+1;
end
end
b = x;
You had the right ideas, but you need to update the variables in your while-loop with every iteration. This is mainly in, where you need to subtract the remainder. And just store the binary remainders in your variable x.
You can check your result with
x = double( dec2bin(d, 16) ) - 48
You could also use a for loop, by pre-calculating the number of iterations with
find( d < 2.^(1:16),1)
and then
if d >=(2^16 -1)
fprintf('This number is too big')
else
for ii = 1:find( d < 2.^(1:16),1)
r = logical(rem(in,y^ii));
x = [r x];
in = in - r*2^(ii-1)
end
end

How to vectorize a matlab script converting a 3d matrix to a single vector?

I am writing a graphical representation of numerical stability of differential operators and I am having trouble removing a nested for loop. The code loops through all entries in the X,Y, plane and calculates the stability value for each point. This is done by finding the roots of a polynomial of a size dependent on an input variable (length of input vector results in a polynomial 3d matrix of size(m,n,(lenght of input vector)). The main nested for loop is as follows.
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
The full code of an example numerical method (Trapezoidal Rule) is as follows. Any and all help is appreciated.
alpha = [-1 1];
beta = [.5 .5];
Wind = 2;
Wsize = 500;
if numel(Wind) == 1
Wind(4) = Wind(1);
Wind(3) = -Wind(1);
Wind(2) = Wind(4);
Wind(1) = Wind(3);
end
if numel(Wsize) == 1
Wsize(2) = Wsize;
end
z1 = linspace(Wind(1),Wind(2),Wsize(1));
z2 = linspace(Wind(3),Wind(4),Wsize(2));
[Z1,Z2] = meshgrid(z1,z2);
z = Z1+1i*Z2;
p = zeros(Wsize(2),Wsize(1),length(alpha));
for n = length(alpha):-1:1
p(:,:,(length(alpha)-n+1)) = alpha(n)-z*beta(n);
end
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
figure()
surf(Z1,Z2,z,'EdgeColor','None');
caxis([0 2])
cmap = jet(255);
cmap((127:129),:) = 0;
colormap(cmap)
view(2);
title(['Alpha Values (',num2str(alpha),') Beta Values (',num2str(beta),')'])
EDIT::
I was able to remove one of the for loops using the reshape command. So;
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
has now become
gg = reshape(p,[numel(p)/length(alpha) length(alpha)]);
r = zeros(numel(p)/length(alpha),1);
for n = 1:numel(p)/length(alpha)
temp = roots(gg(n,:));
if isempty(temp),temp = 0;end
r(n,1) = max(abs(temp));
end
z = reshape(r,[Wsize(2),Wsize(1)]);
This might be one for loop, but I am still going through the same number of elements. Is there a way to use the roots command on all of my rows at the same time?