# How to make and sum up a matrix with upper diagonal direction without for-loop condition [The fastest way!]

조회 수: 5(최근 30일)
HYUNCHUL 2014년 4월 1일
편집: Andrei Bobrov 2014년 4월 2일
A = [1 7 13 0 0 0 0 0 ; 2 8 14 0 0 0 0 0; 3 9 15 0 0 0 0 0 ; 4 10 16 0 0 0 0 0; 5 11 17 0 0 0 0 0; 6 12 18 0 0 0 0 0];
A =
1 7 13 0 0 0 0 0
2 8 14 0 0 0 0 0
3 9 15 0 0 0 0 0
4 10 16 0 0 0 0 0
5 11 17 0 0 0 0 0
6 12 18 0 0 0 0 0
B = [1 7 13 0 0 0 0 0 ; 0 2 8 14 0 0 0 0; 0 0 3 9 15 0 0 0; 0 0 0 4 10 16 0 0; 0 0 0 0 5 11 17 0; 0 0 0 0 0 6 12 18];
B=
1 7 13 0 0 0 0 0
0 2 8 14 0 0 0 0
0 0 3 9 15 0 0 0
0 0 0 4 10 16 0 0
0 0 0 0 5 11 17 0
0 0 0 0 0 6 12 18
How to make the B matrix with the fastest way? After making the B matrix, I will column-wisely sum up the B matrix using "sum" function. This process should be fast due to I am going to do 100 times of this processing with the 100 by 300000 matrix.

댓글을 달려면 로그인하십시오.

### 채택된 답변

Patrik Ek 2014년 4월 1일
편집: Patrik Ek 2014년 4월 1일
This is a fully vectorized operation. And it should be quite efficient. Requires making 2 matrices however.
a = [1 2 0 0;3 4 0 0;5 6 0 0]
vertind = mod(find(a)-1,size(a,1))+1;
aind = find(a);
b = aind+(vertind-1)*size(a,1);
z = zeros(size(a));
z(b) = a(aind)
thesum = sum(b)
The operation on a matrix of your size (100x300000) take 0.1 seconds per iteration (creation of a excluded) and the maximal memory consumption (a included) is ~twice the size of a. The catch is that this does not allow values to go from end to 1, but that can be fixed, by some thinking. The method is based on the way create matrix indice, so to say columnwise. so in a 4x3 matrix element (2,1) have index 5.
The solution is 9 times slower than the one supported by Dishant Arora, but that solution does not return the B matrix.
##### 댓글 수: 1표시숨기기 없음
Dishant Arora 2014년 4월 1일
+1

댓글을 달려면 로그인하십시오.

### 추가 답변(3개)

Dishant Arora 2014년 4월 1일
C = mat2cell(A, ones(1, size(A,1)), size(A,2));
ii = mat2cell(0:size(A,1)-1, 1, ones(1,size(A,1)))';
B = cellfun(@(x,y) circshift(x,[1,y]), C, ii, 'Un', 0);
B = cell2mat(B)
##### 댓글 수: 0표시숨기기 이전 댓글 수: -1

댓글을 달려면 로그인하십시오.

lvn 2014년 4월 1일
Here is one way, which avoids making the B matrix (it directly gives the sum you want, so should be faster on large matrices)
A = [1 7 13 0 0 0 0 0 ; 2 8 14 0 0 0 0 0; 3 9 15 0 0 0 0 0 ; 4 10 16 0 0 0 0 0; 5 11 17 0 0 0 0 0; 6 12 18 0 0 0 0 0];
B = [1 7 13 0 0 0 0 0 ; 0 2 8 14 0 0 0 0; 0 0 3 9 15 0 0 0; 0 0 0 4 10 16 0 0; 0 0 0 0 5 11 17 0; 0 0 0 0 0 6 12 18];
[nrrows,~]=size(A);
C=zeros(1,nrrows+2);
for r=1:nrrows+2
columncounter=max(0,r-nrrows);
for rowcounter=min(r,nrrows):-1:max(1,r-2)
columncounter=columncounter+1;
C(r)=C(r)+A(rowcounter,columncounter);
end
end
C
sum(B)
C =
1 9 24 27 30 33 29 18
ans =
1 9 24 27 30 33 29 18
##### 댓글 수: 0표시숨기기 이전 댓글 수: -1

댓글을 달려면 로그인하십시오.

Andrei Bobrov 2014년 4월 1일
편집: Andrei Bobrov 2014년 4월 2일
[m,n] = size(A);
B = spdiags(A,0:n-1,m,n);
[m,n] = size(A);
B = zeros(size(A));
ii = reshape(find(A),m,[]);
B(bsxfun(@plus,ii,(0:n-size(ii,2))'*m)) = ii;
or
m = size(A);
n = 3;
[ii,jj] = ndgrid(1:m(1),1:n);
B = zeros(m);
B(sub2ind(m,ii,bsxfun(@plus,jj,(0:m(1)-1)'))) = A(1:m(1),1:n);
##### 댓글 수: 2표시숨기기 이전 댓글 수: 1
HYUNCHUL 2014년 4월 1일
Thank you for the correction. your code is really simple and good. However, computational time takes amount time when matrix is large...

댓글을 달려면 로그인하십시오.

### Community Treasure Hunt

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

Start Hunting!