matlab. copy values from one matrix based on values of another matrix - matlab

I have matrix a <500 x 500> and matrix b <500 x 2>.
Matrix b contains two types of values which are row and column coordinates for matrix a. I would like to use the values in matrix b to to copy all the values that fall on the row and column coordinates of matrix a.
see example below
matrix a matrix b output
1 2 3 4 5 1 5 1 2 3 4 5
6 7 8 9 10 2 5 7 8 9 10
11 12 13 14 15 1 3 11 12 13

Because every row will have a different length you'll need to save the values into a cell array.
Something like this should work:
output = cell( size(b,1),1);
for i = 1:size(a,1)
output{i} = a(i, b(i,1):b(i,2) )
end

Related

Summing specific columns for each row in a matrix of double

I would like to sum specific columns of each row in a matrix using a for loop. Below I have included a simplified version of my problem. As of right now, I am calculating the column sums individually, but this is not effective as my actual problem has multiple matrices (data sets).
a = [1 2 3 4 5 6; 4 5 6 7 8 9];
b = [2 2 3 4 4 6; 3 3 3 4 5 5];
% Repeat the 3 lines of code below for row 2 of matrix a
% Repeat the entire process for matrix b
c = sum(a(1,1:3)); % Sum columns 1:3 of row 1
d = sum(a(1,4:6)); % Sum columns 4:6 of row 1
e = sum(a(1,:)); % Sum all columns of row 1
I would like to know how to create a for loop that automatically loops through and sums the specific columns of each row for each matrix that I have.
Thank you.
Here is a solution that you don't need to use for loop.
Assuming that you have a matrix a of size 2x12, and you want to do the row sums every 4 columns, then you can use reshape() and squeeze() to get the final result:
k = 4;
a = [1:12
13:24];
% a =
% 1 2 3 4 5 6 7 8 9 10 11 12
% 13 14 15 16 17 18 19 20 21 22 23 24
s = squeeze(sum(reshape(a,size(a,1),k,[]),2));
and you will get
s =
10 26 42
58 74 90

Independent random selection with replacement of elements per column in a matrix

I have a matrix A which is of size r1 x c. I'm trying to create a matrix B which is of size r2 x c where for each individual column, I would like to randomly sample with replacement.
I wrote this code that does what I am looking for:
%// Define a random index :
RO = randi(r1,r2,c);
%// Define an output matrix
B = zeros(r2,c);
%// Perform selection
for i1 = 1:c
for i2 = 1:r2
B(i2,i1) = A(RO(i2,i1),i1);
end
end
Is there an easier and/or faster way to do this in MATLAB without loops?
If I am interpreting this code correctly, you have a matrix and for each column, you consider this to be an individual signal and you want to randomly sample r2 elements from each signal to create another r2 signal that possibly has duplicates. You wish to stack these columns horizontally to generate an output matrix. A property with this matrix is that for each column, this random sampling is applied only for the corresponding column in the input matrix.
You can certainly do this vectorized. The matrix RO would be used as row coordinates and the column coordinates, which we will call RC, would simply be matrix of enumerations where each row is the linear range 1:c and there are r2 of these stacked on top of each other. This can be achieved with repmat.
First obtain the linear indices of the row and column coordinates via sub2ind then use this to index into your input matrix A.
RO = randi(r1,r2,c);
RC = repmat(1:c,r2,1);
ind = sub2ind(size(A), RO, RC);
B = A(ind);
To show that this works, I've created the following data:
rng(123);
r1 = 5;
r2 = 10;
c = 3;
A = randi(10, r1, c);
Running your code above gives me:
>> B
B =
6 10 8
7 10 5
7 10 4
3 10 4
3 5 5
6 5 1
8 7 4
6 7 8
6 7 5
6 7 4
Using the same matrix RO that was generated, the more optimized code that I wrote also gives:
>> B
B =
6 10 8
7 10 5
7 10 4
3 10 4
3 5 5
6 5 1
8 7 4
6 7 8
6 7 5
6 7 4

dot product of matrix columns

I have a 4x8 matrix which I want to select two different columns of it then derive dot product of them and then divide to norm values of that selected columns, and then repeat this for all possible two different columns and save the vectors in a new matrix. can anyone provide me a matlab code for this purpose?
The code which I supposed to give me the output is:
A=[1 2 3 4 5 6 7 8;1 2 3 4 5 6 7 8;1 2 3 4 5 6 7 8;1 2 3 4 5 6 7 8;];
for i=1:8
for j=1:7
B(:,i)=(A(:,i).*A(:,j+1))/(norm(A(:,i))*norm(A(:,j+1)));
end
end
I would approach this a different way. First, create two matrices where the corresponding columns of each one correspond to a unique pair of columns from your matrix.
Easiest way I can think of is to create all possible combinations of pairs, and eliminate the duplicates. You can do this by creating a meshgrid of values where the outputs X and Y give you a pairing of each pair of vectors and only selecting out the lower triangular part of each matrix offsetting by 1 to get the main diagonal just one below the diagonal.... so do this:
num_columns = size(A,2);
[X,Y] = meshgrid(1:num_columns);
X = X(tril(ones(num_columns),-1)==1); Y = Y(tril(ones(num_columns),-1)==1);
In your case, here's what the grid of coordinates looks like:
>> [X,Y] = meshgrid(1:num_columns)
X =
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
Y =
1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6
7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8
As you can see, if we select out the lower triangular part of each matrix excluding the diagonal, you will get all combinations of pairs that are unique, which is what I did in the last parts of the code. Selecting the lower-part is important because by doing this, MATLAB selects out values column-wise, and traversing the columns of the lower-triangular part of each matrix gives you the exact orderings of each pair of columns in the right order (i.e. 1-2, 1-3, ..., 1-7, 2-3, 2-4, ..., etc.)
The point of all of this is that can then use X and Y to create two new matrices that contain the columns located at each pair of X and Y, then use dot to apply the dot product to each matrix column-wise. We also need to divide the dot product by the multiplication of the magnitudes of the two vectors respectively. You can't use MATLAB's built-in function norm for this because it will compute the matrix norm for matrices. As such, you have to sum over all of the rows for each column respectively for each of the two matrices then multiply both of the results element-wise then take the square root - this is the last step of the process:
matrix1 = A(:,X);
matrix2 = A(:,Y);
B = dot(matrix1, matrix2, 1) ./ sqrt(sum(matrix1.^2,1).*sum(matrix2.^2,1));
I get this for B:
>> B
B =
Columns 1 through 11
1 1 1 1 1 1 1 1 1 1 1
Columns 12 through 22
1 1 1 1 1 1 1 1 1 1 1
Columns 23 through 28
1 1 1 1 1 1
Well.. this isn't useful at all. Why is that? What you are actually doing is finding the cosine angle between two vectors, and since each vector is a scalar multiple of another, the angle that separates each vector is in fact 0, and the cosine of 0 is 1.
You should try this with different values of A so you can see for yourself that it works.
To make this code compatible for copying and pasting, here it is:
%// Define A here:
A = repmat(1:8, 4, 1);
%// Code to produce dot products here
num_columns = size(A,2);
[X,Y] = meshgrid(1:num_columns);
X = X(tril(ones(num_columns),-1)==1); Y = Y(tril(ones(num_columns),-1)==1);
matrix1 = A(:,X);
matrix2 = A(:,Y);
B = dot(matrix1, matrix2, 1) ./ sqrt(sum(matrix1.^2,1).*sum(matrix2.^2,1));
Minor Note
If you have a lot of columns in A, this may be very memory intensive. You can get your original code to work with loops, but you need to change what you're doing at each column.
You can do something like this:
num_columns = nchoosek(size(A,2),2);
B = zeros(1, num_columns);
counter = 1;
for ii = 1 : size(A,2)
for jj = ii+1 : size(A,2)
B(counter) = dot(A(:,ii), A(:,jj), 1) / (norm(A(:,ii))*norm(A(:,jj)));
counter = counter + 1;
end
end
Note that we can use norm because we're specifying vectors for each of the inputs into the function. We first preallocate a matrix B that will contain the dot products of all possible combinations. Then, we go through each pair of combinations - take note that the inner for loop starts from the outer most for loop index added with 1 so you don't look at any duplicates. We take the dot product of the corresponding columns referenced by positions ii and jj and store the results in B. I need an external counter so we can properly access the right slot to place our result in for each pair of columns.

matching two matrices in matlab

Suppose I have two matrices p
p =
1 3 6 7 3 6
8 5 10 10 10 4
5 4 8 9 1 7
5 5 5 3 8 9
9 3 5 4 3 1
3 3 9 10 4 1
then after sorting the columns of matrix p into ascending order
y =
1 3 5 3 1 1
3 3 5 4 3 1
5 3 6 7 3 4
5 4 8 9 4 6
8 5 9 10 8 7
9 5 10 10 10 9
I want to know, given a value from y, what its row was in p
ex: the value 3 which is in matrix p located in row 6 column 1
then after sorting it located in matrix y in row 2 column 1
So I want at the end the values after sorting in matrix y, where it was originally in matrix p
Just use second output of sort:
[y ind] = sort(p);
Your desired result (original row of each value) is in matrix ind.
The Matlab sort command returns a second value which can be used to index into the original array or matrix. From the sort documentation:
[Y,I] = sort(X,DIM,MODE) also returns an index matrix I.
If X is a vector, then Y = X(I).
If X is an m-by-n matrix and DIM=1, then
for j = 1:n, Y(:,j) = X(I(:,j),j); end
Ok i understand exactly what you want.
I will give you my code that i write now, it is not optimal but you can optimize it or i can work with you in order to get the better code..
P and y have the same size.
[n,m]=size(p);
for L=1:m
i=1;
temp=y(i,L);
while(i<=n)
if(temp==y(i,L))
% So it is present in case i of p
disp(['It is present in line' num2str(i) ' of p']);
end
i=i+1;
end
end
Voilà!!

Creating new matrix from existing one

I have a matrix in Matlab, A =
1 2 3
4 5 6
7 8 9
10 11 12
Now I want to create a new matrix B derived from A. The new matrix should look like: B =
1 0
0 4
2 0
0 5
3 0
0 6
Is it possible to solve that without using FOR loop?
Easy with some indexing:
A=[1 2 3 ;
4 5 6 ;
7 8 9 ;
10 11 12 ];
B = zeros(2*size(A,2),2);
B(1:2:end,1)=A(1,:); % put first row values in first column of c
B(2:2:end,2)=A(2,:); % put énd row values in 2nd column of c
If you're only working with 4x4 matrices then yes it is.
You want to convert a 4x4 and using row x column convention you can access A's elements one at at time like so A[row][column]
Then you want a 6x2 matrix then you just call it with zeros B = zeros(6,2)
Then alternate down B[row][column] = A[row][column] and you should be able to build it out easily.