Copying values from one vector to another vector - matlab

I have a vector which is 5000 x 1 & contain doubles, called NewVector. I have another two vectors, one of which is also a 5000 x 1 called OldVector. I then have a vector called CompanyIndex which is a double type as well which contains all the row numbers of OldVector where I would like the data to be copied over to the NewVector. This vector (CompnayIndex) sizes will change every time the code updates.
An example of what I'm looking to do.
Old Vector New Vector CompanyIndex Result I'm looking for - New Vector
3 0 2 0
6 0 3 6
12 0 5 12
9 0 0
36 0 36

Related

how to work with diagonals of a matrix in matlab without using loops?

Lets say I have a matrix and I want to change it's elements.
How can I tell matlab to go the element in the (i,j) place? for
example:
matrix(i;j) ---> if i=j (then do something for example matrix(i;j)^2
else ( do something else)
matrix=rand(n)
if (i=j)
matrix(i,j)=(matrix(i.j))^
else matrix(i,j)=matrix(i,j)*3
end
now how can I reach the matrix's diagonals? I am new to matlab and I didn't find an answer yet :\
I am looking for a hint or something but I can't use loops!
hey i got the answer but lets say i also want the opposite diagonal to be in square how can i do this ?? plz any help
> if a=1 2 3
> 4 5 6
> 7 8 9 i want a at the end to be a= 1 6 9
> 12 25 18
> 49 24 81
It is obvious that you do not know the basics of MATLAB. Here I will try to explain what you need a little bit, but I encourage you to read the basic documentations of programming MATLAB.
If your matrix is called A then each element can be accessed through the indices (number of row and column) of that element, for instance A(2,3) gives you the element on the second row and third column.
Also diag(A) gives all the diagonal elements of A as a vector.
What you have mentioned can be done in different ways, some of which are more efficient than the others but might be more difficult for a beginner. One of the simplest methods is using two for-loops. The first loop moves on the rows of the matrix while the second moves on the column. The goal is to check all the elements one by one.
Here, we use two variables ii and jj to count for matrix rows and columns.
ii moves on the rows, so it has to count from 1 to the number of rows your matrix has. The same is done for columns using variable jj. Moreover, to find the number of rows and columns of the matrix we use function size.
Inside the two for-loops we check if the element is a on the main diagonal with ii==jj and if its not then you do something else to that elements.
for ii=1:size(A,1)
for jj=1:size(A,2)
if ii==jj
A(ii,jj) = A(ii,jj)^2;
else
A(ii,jj) = A(ii,jj)*3;
end
end
end
A way more efficient solution is as follows:
diag(diag(A)).^2 + (tril(A,-1)+triu(A,1))*3
The firs part calculates a diagonal matrix with the elements on the main diagonal of A. The second part gets the upper and lower triangular parts of matrix.
Example:
A = [1 2 3 4;
1 2 3 4;
4 3 2 1;
4 3 2 1];
>> diag(diag(A))
ans =
1 0 0 0
0 2 0 0
0 0 2 0
0 0 0 1
>> (tril(A,-1)+triu(A,1))
ans =
0 2 3 4
1 0 3 4
4 3 0 1
4 3 2 0
Where
diag(diag(A)) + (tril(A,-1)+triu(A,1)) equals to A

Directly create sparse adjacency matrix - (matrix exceeds maxium array size preference)

Problem
I am using an adjacency matrix in my algorithm, which worked fine as long as I tested it an small matrixes (3000) points. But my actual problem includes 167620 points and I would like to create an adjacency matrix for that problem.
But obviously due to the length I get the following problem:
Requested 167620x167620 (209.3GB) array exceeds maximum array size preference. Creation of arrays greater than this limit may take a
long time and cause MATLAB to become unresponsive.
I use the following code:
adjMat = zeros(size(NB_list_all,1));
for ind = 1:size(NB_list_all,1)
adjMat(ind, nonzeros(NB_list_all(ind,2:end))) = 1;
end
adjMatS=sparse(adjMat);
G=digraph(adjMatS);
E=table2array(G.Edges);
As you can see I basically need the Edge-list.
Question
Hence the question: Is there a way to directly compute a sparse adjacency matrix or is there a different way of getting the Edge list from an adjacency list ?
My NB_list_all contains the points in column 1 and neighbours in column 2-5?
EDIT
My NB_list_all is an adajency list of the following form:
1 2 0
2 3 1
3 4 2
4 5 3
5 6 4
6 7 5
7 8 6
8 9 7
9 0 8
Column one the point indize and columns 2:5 the indizes of the points it is adjacent to. 0 if there is no neighbour. The matrix I want to create an Edge list for is 167620x5. I created the edge list before using the E=table2array(G.Edges); graph function of matlab. Now I basically have two questions:
How would i create a sparse adjacency matrix from this adjacency list directly?
Is there an easier way of creating an edge list for this kind of adjacency list ?
Thanks a lot!
If you know all the indexes and values, and the end size of the matrix, a sparse matrix can be created with
adjMat = sparse(indexi,indexj,value,size1,size2);
in a single go. Actually, this is the preffered way of creating a sparse matrix.
Example:
You want the following matrix:
0 1 1
1 0 0
0 0 1
you would build it as:
sparse([1 1 2 3], [2 3 1 3],[1 1 1 1],3,3)
with the example you gave:
NB_list_all=[
1 2 0
2 3 1
3 4 2
4 5 3
5 6 4
6 7 5
7 8 6
8 9 7
9 0 8];
% if the first index contains all numbers we can safely do this
% this is almost indexJ, but we have some zeroes that we dont like
indexJ=NB_list_all(:,2:end);
% create indexI
indexI=repmat(1:size(indexJ,1),size(indexJ,2),1).';
% lets unroll the matrices
indexI=indexI(:);
indexJ=indexJ(:);
% lets remove the indexI and NB_list_all that have a zero somewhere, because those are not real
notzero=find(indexJ);
indexI=indexI(notzero);
indexJ=indexJ(notzero);
adjMat=sparse(indexI,indexJ,1,size(NB_list_all,1),size(NB_list_all,1));

Inserting columns to a matrix in Matlab

I'd like to insert columns to a matrix, but the insertion column positions within the matrix differ by row. How can I do this without using for-loop?
Following is a simplified example in MATLAB;
From A,X,P, I want to get APX without using for-loop.
>> A = zeros(4,5) % inclusive matrix
A =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>> X = [9,8;5,7;8,3;6,7] % data to insert
X =
9 8
5 7
8 3
6 7
>> P = [3;2;4;1] % insertion position within the matrix
P =
3
2
4
1
>> APX = [0,0,9,8,0;0,5,7,0,0;0,0,0,8,3;6,7,0,0,0] % what I want
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
It's simply determining the right column-major indices to access the matrix so you can populate it with your desired values. This first requires generating the right row and column values to access the right positions in APX so you can use X to populate those positions.
Using P, each element tells you which column you should start populating for each row of X. You will need to generate column indices in increasing order up to as many columns as there are in X. To generate the row indices, simply create a matrix that is the same size as X where each column spans from 0 up to as many rows as there are in X minus 1 (i.e. 0:size(X,2)-1). This matrix gives you the correct offsets so that you can take P and add it with this matrix. Once you do that you will have a column index matrix that tells you specifically where each element should go with regards to the columns of the output matrix per row of P. Finally, use sub2ind to generate the column-major indices using the rows and columns generated above to place X in APX.
In other words:
P = [3;2;4;1];
X = [9,8;5,7;8,3;6,7];
rowInd = repmat((1:size(X,1)).', 1, size(X,2)); %'
colInd = bsxfun(#plus, P, 0:size(X,2)-1);
APX = zeros(size(X,1), max(colInd(:)));
APX(sub2ind(size(APX), rowInd, colInd)) = X;
To generate the row locations, we use repmat to create a matrix that is the same size as X where each column spans from 1 up to as many rows as X. To generate the column locations, we use bsxfun to create a matrix where each column is the vector P but increasing by 1 per column. We then create APX to be of compatible size then use sub2ind to finally populate the matrix.
With your above test inputs, we get:
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
Minor Note
You really should actually try using loops before trying it vectorized. Though using loops was slow in previous versions of MATLAB, MATLAB R2015b has an improved JIT engine where loops are now competitive. You should time your code using loops and ensuring that it is justifiable before switching to vectorized implementations.

Delete adjacent repeated terms

I have the following vector a:
a=[8,8,9,9,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8]
From a I want to delete all "adjacent" repetitions to obtain:
b=[8,9,1,2,3,4,5,6,7,8]
However, when I do:
unique(a,'stable')
ans =
8 9 1 2 3 4 5 6 7
You see, unique only really gets the unique elements of a, whereas what I want is to delete the "duplicates"... How do I do this?
It looks like a run-length-encoding problem (check here). You can modify Mohsen's solution to get the desired output. (i.e. I claim no credit for this code, yet the question is not a duplicate in my opinion).
Here is the code:
a =[8,8,9,9,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8]
F=find(diff([a(1)-1, a]));
Since diff(a) returns an array of length (length(a) -1), we want to add a value at the beginning (i.e the a(1)) to get a vector the same size as a. Here we subtract 1 so that, as mentioned by #surgical_tubing, the command find effectively finds it because it looks for non zero elements, so we want to make sure the value is non zero.
Hence diff([a(1)-1, a]) looks like this:
Columns 1 through 8
1 0 1 0 -8 0 1 0
Columns 9 through 16
1 0 1 0 1 0 1 0
Columns 17 through 20
1 0 1 0
Now having found the repeated elements, we index back into a with the positions found by find:
newa=a(F)
and output:
newa =
Columns 1 through 8
8 9 1 2 3 4 5 6
Columns 9 through 10
7 8

How do I sum the max value of every row in a matrix?

A=[ 2 4 8 20 0 0;
1 3 6 18 22 0;
0 3 5 8 18 20]
and then from the above matrix, I want to account average of max value of every rows.
so I wish the result :
result=average(20+22+20)=20,67
thankf for your help.
[C,I] = max(...) finds the indices of the maximum values of A, and returns them in output vector I. If there are several identical maximum values, the index of the first one found is returned.
for your problem
maxValues= max(A,[],2)
result=Mean(maxValues)