Looping through values in a matrix - matlab

I have a Matrix M and I want to run a loop in Matlab whereby the loop variables i,j run through all M(i,j). Can someone provide the syntax please?

First you should first look whether there is a way you could do something using vector operations rather than loops, this is Matlab's strength and usually runs faster. However, if you need to use loops (which sometimes you cannot get around), there are two ways you could do this, the first is to use a single indexing variable (numel is the number of elements in the matrix), this goes through the matrix column by column.
for i = 1:numel(M)
M(i) = %your code here
end
or through each row and column the way you specified (size(M, n) where n is an integer is the size of the nth dimension (1st is number of rows, 2nd is number of columns, 3rd is the number of levels, ...))
for i = 1:size(M, 1)
for j = 1:size(M, 2)
M(i, j) = %your code here
end
end

Related

Is there a way to parse each row of a matrix in Octave?

I am new to Octave and I wanted to know if there is a way to parse each row of a matrix and use it individually. Ultimately I want to use the rows to check if they are all vertical to each other (the dot product have to be equal to 0 for two vectors to be vertical to each other) so if you have some ideas about that I would love to hear them. Also I wanted to know if there is a function to determine the length (or the amplitude) of a vector.
Thank you in advance.
If by "parse each row" you mean a loop that takes each row one by one, you only need a for loop over the transposed matrix. This works because the for loop takes successive columns of its argument.
Example:
A = [10 20; 30 40; 50 60];
for row = A.'; % loop over columns of transposed matrix
row = row.'; % transpose back to obtain rows of the original matrix
disp(row); % do whatever you need with each row
end
However, loops can often be avoided in Matlab/Octave, in favour of vectorized code. For the specific case you mention, computing the dot product between each pair of rows of A is the same as computing the matrix product of A times itself transposed:
A*A.'
However, for the general case of a complex matrix, the dot product is defined with a complex conjugate, so you should use the complex-conjugate transpose:
P = A*A';
Now P(m,n) contains the dot product of the n-th and m-th rows of A. The condition you want to test is equivalent to P being a diagonal matrix:
result = isdiag(P); % gives true of false

Vectorizing a parallel FOR loop across multiple dimensions MATLAB

Please correct me if there are somethings unclear in this question. I have two matrices pop, and ben of 3 dimensions. Call these dimensions as c,t,w . I want to repeat the exact same process I describe below for all of the c dimensions, without using a for loop as that is slow. For the discussion below, fix a value of the dimension c, to explain my thinking, later I will give a MWE. So when c is fixed I have a 2D matrix with dimension t,w.
Now I repeat the entire process (coming below!) for all of the w dimension.
If the value of u is zero, then I find the next non zero entry in this same t dimension. I save both this entry as well as the corresponding t index. If the value of u is non zero, I simply store this value and the corresponding t index. Call the index as i - note i would be of dimension (c,t,w). The last entry of every u(c,:,w) is guaranteed to be non zero.
Example if the u(c,:,w) vector is [ 3 0 4 2 0 1], then the corresponding i values are [1,3,3,4,6,6].
Now I take these entries and define a new 3d array of dimension (c,t,w) as follows. I take my B array and do the following what is not a correct syntax but to explain you: B(c,t,w)/u(c,i(c,t,w),w). Meaning I take the B values and divide it by the u values corresponding to the non zero indices of u from i that I computed.
For the above example, the denominator would be [3,4,4,2,1,1]. I hope that makes sense!!
QUESTION:
To do this, as this process simply repeats for all c, I can do a very fast vectorizable calculation for a single c. But for multiple c I do not know how to avoid the for loop. I don't knw how to do vectorizable calculations across dimensions.
Here is what I did, where c_size is the dimension of c.
for c=c_size:-1:1
uu=squeeze(pop(c,:,:)) ; % EXTRACT A 2D MATRIX FROM pop.
BB=squeeze(B(c,:,:)) ; % EXTRACT A 2D MATRIX FROM B
ii = nan(size(uu)); % Start with all nan values
[dum_row, ~] = find(uu); % Get row indices of non-zero values
ii(uu ~= 0) = dum_row; % Place row indices in locations of non-zero values
ii = cummin(ii, 1, 'reverse'); % Column-wise cumulative minimum, starting from bottomi
dum_i = ii+(time_size+1).*repmat(0:(scenario_size-1), time_size+1, 1); % Create linear index
ben(c,:,:) = BB(dum_i)./uu(dum_i);
i(c,:,:) = ii ;
clear dum_i dum_row uu BB ii
end
The central question is to avoid this for loop.
Related questions:
Vectorizable FIND function with if statement MATLAB
Efficiently finding non zero numbers from a large matrix
Vectorizable FIND function with if statement MATLAB

How to replace multiple values in a matrix in matlab

I'm trying to turn N number of zeros into a "1". My code works to change only one zero at a time. What is the best way to simultaneously change the zeros into a "1" N number of times?
N=4;
board=zeros(N);
board(randi(numel(board)))=1
Thank you
Edit:
N=4;
board=zeros(N);
x=1;
while (x<=N)
board(randi(numel(board)))=1;
x=x+1;
end
Would it be possible to get this to work? It's not giving me an error, but it's not giving me an output either...
I am suggesting a small improvement over atru's answer. All you need to do is this:
N=4;
board=zeros(N);
board(randperm(numel(board), N)) = 1;
Here randperm will basically generate N random numbers from the set 1:(N*N) to fill your matrix
You can generate an NxN matrix of 0s with M randomly placed 1s in a single line
myMatrix = reshape(randperm(N^2)<=M, N, N);
Just replace M with N in your specific case.
This is one way to do it while avoiding an explicit for loop
N=4;
board=zeros(N);
ind_1s = randperm(N*N);
board(ind_1s(1:N)) = 1;
This generates random permutations of all matrix indices and then it fills first N with 1s.
Your solution will work too but it needs a condition for cases when the newly chosen index already has a 1 in there
N=4;
board=zeros(N);
x=1;
while (x<=N)
ind_1s = randi(numel(board));
if board(ind_1s)==0
board(ind_1s)=1;
x=x+1;
end
end
For large matrices the first one may be better performance wise, but that would need to be check with matlab profiler or simple timing.

Remove duplicates in correlations in matlab

Please see the following issue:
P=rand(4,4);
for i=1:size(P,2)
for j=1:size(P,2)
[r,p]=corr(P(:,i),P(:,j))
end
end
Clearly, the loop will cause the number of correlations to be doubled (i.e., corr(P(:,1),P(:,4)) and corr(P(:,4),P(:,1)). Does anyone have a suggestion on how to avoid this? Perhaps not using a loop?
Thanks!
I have four suggestions for you, depending on what exactly you are doing to compute your matrices. I'm assuming the example you gave is a simplified version of what needs to be done.
First Method - Adjusting the inner loop index
One thing you can do is change your j loop index so that it only goes from 1 up to i. This way, you get a lower triangular matrix and just concentrate on the values within the lower triangular half of your matrix. The upper half would essentially be all set to zero. In other words:
for i = 1 : size(P,2)
for j = 1 : i
%// Your code here
end
end
Second Method - Leave it unchanged, but then use unique
You can go ahead and use the same matrix like you did before with the full two for loops, but you can then filter the duplicates by using unique. In other words, you can do this:
[Y,indices] = unique(P);
Y will give you a list of unique values within the matrix P and indices will give you the locations of where these occurred within P. Note that these are column major indices, and so if you wanted to find the row and column locations of where these locations occur, you can do:
[rows,cols] = ind2sub(size(P), indices);
Third Method - Use pdist and squareform
Since you're looking for a solution that requires no loops, take a look at the pdist function. Given a M x N matrix, pdist will find distances between each pair of rows in a matrix. squareform will then transform these distances into a matrix like what you have seen above. In other words, do this:
dists = pdist(P.', 'correlation');
distMatrix = squareform(dists);
Fourth Method - Use the corr method straight out of the box
You can just use corr in the following way:
[rho, pvals] = corr(P);
corr in this case will produce a m x m matrix that contains the correlation coefficient between each pair of columns an n x m matrix stored in P.
Hopefully one of these will work!
this works ?
for i=1:size(P,2)
for j=1:i
Since you are just correlating each column with the other, then why not just use (straight from the documentation)
[Rho,Pval] = corr(P);
I don't have the Statistics Toolbox, but according to http://www.mathworks.com/help/stats/corr.html,
corr(X) returns a p-by-p matrix containing the pairwise linear correlation coefficient between each pair of columns in the n-by-p matrix X.

Matlab for loop - How to index?

I'm pretty rusty with Matlab programming and I'm stuck writing a for loop. I want to generate n random numbers using the formula x(i+1)=mod(a*x(i), m);
What I have is
for i=1:n
x(i+1)=mod(a*x(i),m);
end
What I don't know, is
How do I set x?
Once I set x, would the index be correct?
You should preallocate x for a case like this. Given your for loop, the minimum index is 1 and maximum index is n+1 so x needs to be a vector with n+1 elements. You could use zeros, for example:
x = zeros(n+1,1); % An n+1 by 1 column vector
It looks like you should also set the value of x(1) to some kind of initial value too. Your for loop is effectively a recurrence relation where the i+1-th value of x depends on the i-th value.