Filling a matrix with vectors in loop and apply operation - matlab

I am working on matlab with a matrix. I would like to reproduce this matrix and apply sum for elements in rows.
I have two vectors defined by this code:
unitsvector=1:5;
reordervector=1:3;
Then, I create an empty matrix to store the values:
resultvec=zeros(size(unitsvector,2)*size(reordervector,2),3);
Finally, here is the loop I use but it is not working:
for a=1:length(resultvec)
for b=reordervector
for c=unitsvector
resultvec(a,1)=b;
resultvec(a,2)=c;
resultvec(a,3)=b+c;
end
end
end
How could I reproduce this matrix in matlab. Thanks for your help.

You can use meshgrid for this without a for loop.
[a,b] = meshgrid(1:5,1:3);
M = [a(:) b(:)];
M(:,3) = sum(M,2); % Create third column by summing first two

Why are you looping at all? sum actually has vector support; a simple resultvec = [a(:,1),a(:,2),sum(a,2)] would work.
As to your code: of course it doesn't work. What do you expect to be the contents of a? You create a as a loop index, which runs over the range 1:length(resultvec). Ergo, within each loop iteration a is a scalar. You try to call it like it is a three-element vector. Nor do you define b and c. This might be possible in R, judging where you're coming from, but not in MATLAB.

Related

How to plot a function with an exponential multiplied by a sine function?

Hello I need help plotting the below equation in matlab.
v=10.0004+10.229*e^(-3*t)*sin(5.196*t-257.856)
here is what I have but I keep getting an error:
t=[0:0.1:2];
v=10.0004+10.229*exp(t)*sin(5.196*t+257.856);
plot(t,v)
Error using *
Incorrect dimensions for matrix multiplication. Check that the number of columns in the first matrix matches the
number of rows in the second matrix. To perform elementwise multiplication, use '.*'.
Error in example (line 2)
v=10.0004+10.229*exp(t)*sin(5.196*t+257.856);
Because t is a matrix, you cannot simply input it as you would a single variable. You have to access each value individually and calculate a corresponding v, then you store that value and move on. Rinse and repeat for each value.
This can be visualized with a for loop. Get the length of your time variable, which will determine how many values you need to calculate, then let the loop run for the corresponding number of elements. Make sure the loop counter is also used to index each element in v.
t = 0:0.1:2 ;
%For each element (n) in t, create a corresponding one of v.
for n = 1:length(t)
v(n) = 10.0004+10.229*exp(t(n))*sin(5.196*t(n)+257.856);
end
plot(t,v)
As we can interpret from the loop, there is a need to do element-wise (good keyword to remember) multiplication. In other languages, you might HAVE to use the loop method. Luckily in Matlab there is a dedicated operator for this '.*'. Therefore in Matlab you could simply modify your code as follows:
t=[0:0.1:2];
v=10.0004+10.229.*exp(t).*sin(5.196.*t+257.856);
plot(t,v)
Either method gives you the desired plot. The first I included to illustrate the underlying logic of what you're looking to do, and the second to simply it with Matlab's syntax. Hope this helps guide you in the future.
Best of luck out there.

Matlab create matrix by iterating the same command several times without for loop

I have a code like this:
A = [sparse(round(rand(4,4)))];
B = [sparse(round(rand(1,4)))];
C = [bsxfun(#minus,A(1,:),B); bsxfun(#minus,A(2,:),B); bsxfun(#minus,A(3,:),B); bsxfun(#minus,A(4,:),B);]
Is is possible to somehow define C this way for a large amount rows (so that I cannot physically print the command this way) WITHOUT a loop (because a loop would take an excessively long time)?
One another options:
If you prefer to keep a sparse matrix:
C = A - repmat(B,size(A,1),1); %but slower than the bsxfun version.
If you pass a matrix and a row vector to bsxfun, it will automatically apply the vector to all rows of the matrix, so just use:
C = bsxfun(#minus, A, B);
This will substract the row vector B to all rows of matrix A, no matter how many rows you have.
EDIT: If you have two matrices instead of a Matrix and a Vector, you can either use permutations or arrayfun. Take a look at:
Multiply all columns of one matrix by another matrix with bsxfun

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.

Correlation coefficient between rows of two matrices

I have the following code, how will I be able to simplify it using the function as it currently runs pretty slow, assume X is 10x7 and Y is 4x7 and D is a matrix stores the correlation between each pair of vectors. If the solution is to use the xcorr2 function can someone show me how it is done?
for i = 1:4
for j = 1:10
D(j,i) = corr2(X(j,:),Y(i,:));
end
end
Use pdist2 (Statistics toolbox) with 'correlation' option. It's faster than your code (even with preallocation), and requires just one line:
D = 1-pdist2(X,Y,'correlation');
Here is how I would do it:
First of all, store/process your matrix transposed. This makes for easier use of the correlation function.
Now assuming you have matrices X and Y and want to get the correlations between combinations of columns, this is easily achieved with a single loop:
Take the first column of X
use corrcoef to determine the correlation with all columns of Y at once.
As long as there is one, take the next column of X
Alternate to this, you can check whether it helps to replace corr2 in your original code with corr, xcorr or corrcoef and see which one runs fastest.
With corrcoef you can do this without a loop, and without using a toolbox:
D = corrcoef([X', Y']);
D = D(1 : size(X, 1), end - size(Y, 1) + 1 : end);
A drawback is that more coefficients are computed than necessary.
The transpose is necessary because your matrices do not follow the Matlab convention to enumerate samples with the first index and variables with the second.

apply matrix randomisation without for loop in matlab

A question about matlab and randomisation of a 3d matrix respecting the rows and columns.
I have a n x n x s matrix M and I want to mess it up a bit, but with some control.
I can achieve my wish with a for loop
for j=1:size(M,3)
r=randperm(size(M,1));
random_M(:,:,j)=M(r,r,j);
end
Is there a way to perform this without having to loop over j? I need many randomisation iterations and could afford the benefits of indexing.
Cheers!
edit: Some more thoughts following Alexandrew's comments
I have created a function that randomises a squeezed version of M:
function randomMat=randomiseMat(Mat)
[rows,cols]=size(Mat);
r=randperm(rows);
randomMat=Mat(r,r);
then, using arrayfun I seem to get what I want:
randomM=arrayfun(#(x) randomiseMat(M(:,:,x)),1:size(M,3),'UniformOutput', false)
however, randomM is now a cell array of size (1,size(M,3)) with each cell containing randomised array.
Is there a way to make it in a 3d matrix just like the input M?
You can calculate all the values for r in one go, and then use arrayfun:
[nRows,nCols,nPages] = size(M);
[~,r]=sort(rand(nRows,nPages));
%# you should test on a realistic example whether a for-loop
%# isn't faster here
outCell = arrayfun(#(x) M(r(:,x),r(:,x),x), 1:nPages,'UniformOutput',false);
randomM = cat(3,outCell{:});