sorting matrix in matlab based on another vector - arrays

I have a 2D matrix and want to sort rows and columns based on two other vectors i.e. one for ordering rows another for ordering columns in MATLAB
Example: A (Matrix to order)
0 1 2 3 4
1 1 8 9 7
2 3 4 6 2
3 1 2 0 8
Row Vector (Order for sorting rows of matrix A)
1
4
2
3
And column vector
1 5 4 2 3
Modified A
0 4 3 1 2
3 8 0 1 2
1 7 9 1 8
2 2 6 3 4

How about:
ModifiedA=A(RowVector,ColumnVector);
Note: Matab's indexing starts at 1 not at 0, adapt your indexing vectors accordingly.

In MATLAB, you can use the second output of sort to get the 1-based indexes that MATLAB is looking for (in this case you could have just added 1, but using sort works even if the row and column vectors are not consecutive).
[~,rowIdx] = sort(rowVector);
[~,colIdx] = sort(colVector);
And then you can apply the indexing operation to the matrix:
modifiedA = A(rowIdx, colIdx);

Related

Creating multidimensional shifting array using a vectorize approach instead of FOR loop

I can "Vectorize" the circshift command but I'm having trouble adding dimensions to it.
See code below with working FOR loop that I'm trying to vectorize using dimensions
clear all,clf reset,tic,clc , close all
function [outMat] = vectcircshift(vectToShift,shiftVector)
%This function generates a matrix where each row is a circshift of the
%original vector from the specified interval in the shiftVector;
%
%Inputs
%vectToShift: is the original vector you want to circshift multiple times
%shiftVector: is the vector of the circshift sizes;
%
%Outputs
%outMat: is a matrix were every row is circshift by the amount in the
% shiftVector
[n,m]=size(vectToShift);
if n>m
inds=(1:n)';
i=toeplitz(flipud(inds),circshift(inds,[1 0]));
outMat=vectToShift(i(shiftVector,:));
outMat=circshift(outMat,[0,-1]); %shift to include original signal first
else
inds=1:m;
i=toeplitz(fliplr(inds),circshift(inds,[0 1]));
outMat=vectToShift(i(shiftVector,:));
outMat=circshift(outMat,[0,-1]); %shift to include original signal first
end
end
%%----Working FOR LOOP below I'm trying to vectorize.
ndim=0;
ndim_tot=[1:3] %total dimensions
for ndim=1:length(ndim_tot)
ndim=ndim+0
if ndim==1
array_sort(ndim,:)=circshift(ndim_tot,[0 ndim-1]) %start at row of sort array
else
array_sort(ndim,:)=circshift(ndim_tot,[0 mod(-ndim,length(ndim_tot))+1]) %next start of row of sort array
endif
array_sort= array_sort(ndim,:)
array_dim(:,:,ndim)=vectcircshift([1:5],array_sort)
endfor
I tired the syntax below but that logic won't work.
ndim_tot=[1:3]; %number of dimensions
array_dim2(:,:,ndim_tot)=vectcircshift([1:5],[1:3])
I get an error nonconformant arguments(op1 is 0x0x1, op2 is 3x5)
My goal is to create a multidimensional array that circshifts a signal / array and also creates and shifts it in multiple dimensions.
Example: of what the multidimensional array would look like
if I start with a signal / array a1=[1 2 3 4 5]
I'm trying to have it create.
array_dim(:,:,1)=
[
1 2 3 4 5
5 1 2 3 4
4 5 1 2 3
]
array_dim(:,:,2)=
[
5 1 2 3 4
4 5 1 2 3
1 2 3 4 5
]
array_dim(:,:,3)=
[
4 5 1 2 3
1 2 3 4 5
5 1 2 3 4
]
Please note: the the numbers won't be sequential I just used it as an example to help explain things a little easier.
PS: I'm using Octave 4.2.2
Not clear why you are shifting in mod 3, but here is a loop assignment using shift
a1=[1 2 3 4 5];
array_dim=zeros(3,5,3);
for i=0:2
array_dim(:,:,i+1)=[shift(a1,i);
shift(a1,mod(i+1,3));
shift(a1,mod(i+2,3))];
endfor
array_dim
and the output fits your example
array_dim =
ans(:,:,1) =
1 2 3 4 5
5 1 2 3 4
4 5 1 2 3
ans(:,:,2) =
5 1 2 3 4
4 5 1 2 3
1 2 3 4 5
ans(:,:,3) =
4 5 1 2 3
1 2 3 4 5
5 1 2 3 4

Matrix transformation in MATLAB

For example, I have a matrix A (Figure 1). When the variable n = 2, I want it to be transformed to the matrix B. The red rectangle shows the transformation rule of every column. According to this rule, when the n = 3, it can become the matrix C.
I have written a script using a for loop method, but it is a waste of time when the matrix A is very large (e.g. 11688* 140000). Is there an efficient way to solve this problem?
Figure 1:
Here is a way using reshape and implicit expansion:
result = reshape(A((1:size(A,1)-n+1) + (0:n-1).', :), n, []);
For example assume that n = 3. Implicit expansion is used to extract indices of rows:
row_ind = (1:size(A,1)-n+1) + (0:n-1).';
The following matrix is created:
1 2
2 3
3 4
Extract the desired rows of A:
A_expanded = A(row_ind, :)
When the matrix row_ind is used as an index it behaves like a vector:
1
2
1 2 3
2 3 -> 2
3 4 3
4
A_expanded =
3 5 7
6 8 9
2 6 3
6 8 9
2 6 3
1 2 1
Now A_expanded can be reshaped to the desired size:
result = reshape(A_expanded, n, []);
>>result =
3 6 5 8 7 9
6 2 8 6 9 3
2 1 6 2 3 1
If you have the Image Processing Toolbox you can use im2col as follows:
result = im2col(A, [n 1], 'sliding');

reshaping and re-arranging array using octave / matlab

I'm trying to reshape an array, perform an operation and then reshape it back to the original. See example of the output I'm trying to get. I can get a and b but I'm having trouble getting c to look like a again.
Step 1) (the original array)
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
Step 2) (reshape and perform some operation)
1,1,1,2,2,2,3,3,3,4,4,4,5,5,5
Step 3) (array is reshaped back to the original size to look like step 1) this is what I want
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
I can get the variables a and b but I'm not sure how to reshape c from b to look like a again see example code and output below
a=[repmat(1,[1,3]);repmat(2,[1,3]);repmat(3,[1,3]);repmat(4,[1,3]);repmat(5,[1,3])]
[rw,col]=size(a)
b=reshape(a',1,rw*col)
c=reshape(b,rw,col)
a=
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
b=1,1,1,2,2,2,3,3,3,4,4,4,5,5,5
c =
1 2 4
1 3 4
1 3 5
2 3 5
2 4 5
Ps: I'm using Octave 4.0 which is like Matlab.
MATLAB and Octave use column-major ordering so you'll need to reshape the result with that in mind. The data will be filled down the columns first but you want it to fill the columns first. To achieve this, you can specify the number of columns as the number of rows provided to reshape and then transpose the result
c = reshape(b, 3, []).'
Or more flexibly
c = reshape(b, flip(size(a))).'

All row-combinations of a matrix in a new matrix with matlab

I have got a question regarding all the combinations of matrix-rows in Matlab.
I currently have a matrix with the following structure:
1 2
1 3
1 4
2 3
2 4
3 4
Now I want to get all the possible combinations of these "pairs" without using a number twice in the same row:
1 2 3 4
1 3 2 4
1 4 2 3
And it must be possible to make it with n-"doublecolumns". Which means, when my pair-matrix goes for example until "5 6", i want to create the matrix with 3 of these doublecolumns:
1 2 3 4 5 6
1 2 3 5 4 6
1 2 3 6 4 5
1 3 2 4 5 6
1 3 2 5 4 6
....
I hope you understand what I mean :)
Any ideas how to solve this?
Thanks and best regard
Jonas
M = [1 2
1 3
1 4
2 3
2 4
3 4]; %// example data
n = floor(max(M(:))/2); %// size of tuples. Compute this way, or set manually
p = nchoosek(1:size(M,1), n).'; %'// generate all n-tuples of row indices
R = reshape(M(p,:).', n*size(M,2), []).'; %// generate result...
R = R(all(diff(sort(R.'))),:); %'//...removing combinations with repeated values

Algorithm for Vertex connections From List of Directed Edges

The square of a directed graph G = (V, E) is the graph G2 = (V, E2) such that u→w is in E2 if and only if u ≠ w and there is a vertex v such that both u→v and v→w are in E2. The input file simply lists the edges in arbitrary order as ordered pairs of vertices, with each edge on a separate line. The vertices are numbered in order from 1 to the total number of vertices.
*self-loops and duplicate/parallel edges are not allowed
If we look at the an example of input data:
1 6
1 4
1 3
2 4
2 8
2 6
2 5
3 5
3 2
3 6
4 7
4 5
4 6
4 8
5 1
5 8
5 7
6 3
6 4
7 5
7 4
7 6
8 1
Then the output would be:
1: 3 4 7 8 5 2 6
2: 5 6 3 4 1 8 7
3: 1 7 8 6 5 4
4: 5 6 8 7 3 1
5: 3 1 4 6
6: 2 7 5 8
7: 1 5 6 8 3 4
8: 6 4 3
I'm writing the code in C.
My thoughts are to run through the file, see how many vertices they are and then allocate an array of pointers. Proceed to go through the list again searching for just where the line has a 1 in it, then look at where those corresponding numbers lead. If its not a duplicate or the same number(1) then I'll add it to a linked list, from the array of pointers. I will do this for every number vertex number in the file.
However, I feel this is terribly inefficient, and not the best way to go about doing this. If anyone has any other suggestions I would be extremely grateful.
if I get it right, you want to build a result set for each node where all nodes with a distance of one and two for each node are stated.
therefore, one can hold the edges in an adjacency matrix of bit arrays, where a bit is one when an edge exists and zero if not.
now one can multiply this matrix with itself. in this case multiply means you can make an AND on row and column.
A small example (sorry, don't know how to insert a matrix properly):
0 1 0 0 1 0 0 0 1
0 0 1 x 0 0 1 = 1 1 0
1 1 0 1 1 0 0 1 1
This matrix contains a one for all nodes reachable in two steps. simply it's the adjacency matrix for two instead of one steps. If you now OR this matrix with your initial matrix you have a matrix which holds all paths of length one and two.
this approach has multiple advantages. at first bit operations are very fast. the cpu parallyzes your calculations and you can stop for the result matrix cell if one pair is found where the results gives one.
furthermore it is well documented how to calculate matrix multiplication in parallel.
you can easily calculate all other length of pathes. for a length k one has to calculate:
A^k = A^(k-1) * A
hope that helped

Resources