How to create a specific matrix from a regular matrix

I wanna create a specific matrix B from a regular matrix A as following in Matlab. Is there anyone who can help me to use a better method to generate it, not for loop? The matrix size could be various. In example, it's 3 by 3 matrix. It could be 3 by n matrix. Thanks
A=[ a b c;
d e f;
g h i]
B=[a 0 0;
d b 0;
g e c;
0 h f;
0 0 i]

3 Comments

What is the relation between A and B?
B is like A that is rotated 45 degrees down.
all diagonal lines(right top to left down) from matrix A

Sign in to comment.

 Accepted Answer

A=[ 1 2 3;4 5 6;7 8 9]
[n,m]=size(A)
B=[A;zeros(n-1,m)]
out=cell2mat(arrayfun(@(x) circshift(B(:,x),[x-1 0]),1:m,'un',0))

6 Comments

Thanks for your answer. The solution you provided can just solve 3 by 3 matrix, not for 3 by n matrix dynamically, such as: 3 by 5 matrix. Please help me for that. Thanks
There is no big changes
[n,m]=size(A)
B=[A;zeros(m-1,m)]
out=cell2mat(arrayfun(@(x) circshift(B(:,x),[x-1 0]),1:m,'un',0))
Speed test for 3x1000 array in a for loop (100)
'Azzi' 'Cedric' 'Andrei' 'Jos'
[9.5960] [0.1596] [3.5598] [2.4450]
Cedric
Cedric on 29 Aug 2013
Edited: Cedric on 29 Aug 2013
Huh, I wouldn't have guessed that SPDIAGS was that fast, thank you for the test! Did you try with a square A matrix, or, to take the other extreme, a 1000x3 matrix?
I did the test with a 1000x3 matrix
You wrote 3x1000 actually, which should produce a significantly sparse 1002x1000 output, whereas the 1000x3 should produce a significantly dense 1002x3 output.

Sign in to comment.

More Answers (4)

Cedric
Cedric on 29 Aug 2013
Edited: Cedric on 29 Aug 2013
Here is a one-liner. Assume
>> A = randi(20, 3, 4) % Example.
A =
19 16 2 16
6 8 2 19
16 12 11 3
then
>> B = full(spdiags(A.', 1-(1:size(A,1)), sum(size(A))-1, size(A,2)))
B =
19 0 0 0
6 16 0 0
16 8 2 0
0 12 2 16
0 0 11 19
0 0 0 3
is what you are looking for. Note that it is not the fastest solution, but it is appropriate for A matrices with nCols >> nRows. In such case, remove the call to FULL and keep the solution sparse.
Very simple:
B = [A(1,1), 0, 0;
A(2,1), A(1,2), 0;
A(3,1), A(2,2), A(1,3);
0, A(3,2), A(2,3);
0, 0, A(3,3)];

3 Comments

For the 3 row by n column case, maybe something with kron, hankel, or toeplitz but I'll leave it to someone smarter than me to figure that out.
This is not what I expected. This matrix size could be various dynamically, for example: 3 by 7, 3 by 21. Therefore, I need few code to create it. Thanks
What would you expect this to give as a result:
A=[ 1 2 3 4 5 6;
7 8 9 10 11 12;
13 14 15 16 17 18]

Sign in to comment.

Just for fun and to show the power of logical indexing:
A = reshape(1:12,3,[]).' % input
[m,n] = size(A) ;
tmp = cumsum(cumsum(eye(n+m-1,n)))
B = double(tmp & (tmp < m+1))
B(logical(B)) = A
[m,n] = size(A);
B = ones(m+n-1,n);
p = tril(B) & rot90( tril(B),2);
B = B - 1;
B(p) = A;

Categories

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!