transforming a matrix into a vector along its diagonals
im not not a programmer, i just need to solve something numerically in matlab. i need a function to make the following transformation for any square matrix:
from
row 1: 1 2 3
row 2: 4 5 6
row 3: 7 8 9
to
1 4 2 7 5 3 8 6 9
ie write the matrix i开发者_StackOverflow中文版n a vector along its diagonals from left to top right. any ideas please?
i really need a little more help though:
say the matrix that we have transformed into the vector, has entries denoted by M(i,j), where i are rows and j columns. now i need to be able to find out from a position in the vector, the original position in the matrix, i.e say if its 3rd entry in the vector, i need a function that would give me i=1 j=2. any ideas please? im really stuck on this:( thanks
This is quite similar to a previous question on traversing the matrix in a zigzag order. With slight modification we get:
A = rand(3); %# input matrix
ind = reshape(1:numel(A), size(A)); %# indices of elements
ind = spdiags(fliplr(ind)); %# get the anti-diagonals
ind = ind(end:-1:1); %# reverse order
ind = ind(ind~=0); %# keep non-zero indices
B = A(ind); %# get elements in desired order
using the SPDIAGS function. The advantage of this is that it works for any arbitrary matrix size (not just square matrices). Example:
A =
0.75127 0.69908 0.54722 0.25751
0.2551 0.8909 0.13862 0.84072
0.50596 0.95929 0.14929 0.25428
B =
Columns 1 through 6
0.75127 0.2551 0.69908 0.50596 0.8909 0.54722
Columns 7 through 12
0.95929 0.13862 0.25751 0.14929 0.84072 0.25428
Here's one way to do this.
%# n is the number of rows (or cols) of the square array
n = 3;
array = [1 2 3;4 5 6;7 8 9]; %# this is the array we'll reorder
%# create list of indices that allow us
%# to read the array in the proper order
hh = hankel(1:n,n:(2*n-1)); %# creates a matrix with numbered antidiagonals
[dummy,sortIdx] = sort(hh(:)); %# sortIdx contains the new order
%# reorder the array
array(sortIdx)
ans =
1 4 2 7 5 3 8 6 9
You can convert your matrix to a vector using the function HANKEL to generate indices into the matrix. Here's a shortened version of Jonas' answer, using M
as your sample matrix given above:
N = size(M,1);
A = hankel(1:N,N:(2*N-1));
[junk,sortIndex] = sort(A(:));
Now, you can use sortIndex
to change your matrix M
to a vector vec
like so:
vec = M(sortIndex);
And if you want to get the row and column indices (rIndex
and cIndex
) into your original matrix that correspond to the values in vec
, you can use the function IND2SUB:
[rIndex,cIndex] = ind2sub(N,sortIndex);
A=[1,2,3;4,5,6;7,8,9];
d = size(A,1);
X=[];
for n = 1:2*size(A,1) - 1
j = min(n,d); i = (n+1)-(j);
X = cat(2,X,diag(flipud(A(i:j,i:j)))');
end
X
X =
1 4 2 7 5 3 8 6 9
You can generate the diagonals in this way:
for i = -2:2
diag(flipud(a), i)
end
I don't know whether this is the optimal way to concatenate the diagonals:
d = []
for i = -2:2
d = vertcat(d, diag(flipud(a), i))
end
(I tested it in octave, not in matlab)
精彩评论