How to make and sum up a matrix with upper diagonal direction without for-loop condition [The fastest way!]
조회 수: 1 (최근 30일)
이전 댓글 표시
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.
Please help me out!
댓글 수: 0
채택된 답변
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.
추가 답변 (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
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
Andrei Bobrov
2014년 4월 1일
편집: Andrei Bobrov
2014년 4월 2일
[m,n] = size(A);
B = spdiags(A,0:n-1,m,n);
ADD other way
[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);
참고 항목
카테고리
Help Center 및 File Exchange에서 Logical에 대해 자세히 알아보기
제품
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!