Suppose I have a matrix A
of dimension Nx(N-1)
in MATLAB, e.g.
N=5;
A=[1 2 3 4;
5 6 7 8;
9 10 11 12;
13 14 15 16;
17 18 19 20 ];
I want to transform A
into an NxN
matrix B
, just by adding a zero diagonal, i.e.,
B=[ 0 1 2 3 4;
5 0 6 7 8;
9 10 0 11 12;
13 14 15 0 16;
17 18 19 20 0];
This code does what I want:
B_temp = zeros(N,N);
B_temp(1,:) = [0 A(1,:)];
B_temp(N,:) = [A(N,:) 0];
for j=2:N-1
B_temp(j,:)= [A(j,1:j-1) 0 A(j,j:end)];
end
B = B_temp;
Could you suggest an efficient way to vectorise it?
Generate a matrix with zeros at diagonal and ones at non-diagonal indices. Replace the non-diagonal elements with the transpose of
A
(since MATLAB is column major). Transpose again to get the correct order.Edit:
As suggested by Wolfie for the same algorithm, you can get rid of conversion to
double
and the use offind
with:If you want to insert any vector on a diagonal of a matrix, one can use plain indexing. The following snippet gives you the indices of the desired diagonal, given the size of the square matrix
n
(matrix isn
byn
), and the number of the diagonalk
, wherek=0
corresponds to the main diagonal, positive numbers ofk
to upper diagonals and negative numbers ofk
to lower diagonals.ixd
finally gives you the 2D indices.Usage:
You can do this with upper and lower triangular parts of the matrix (
triu
andtril
).Then it's a 1 line solution:
Edit: benchmark
This is a comparison of the loop method, the 2 methods in Sardar's answer, and my method above.
Benchmark code, using
timeit
for timing and directly lifting code from question and answers:Results:
Conclusions:
find
for large matrices is important, saving ~35% processing time between Sardar's methods.