Sum over all diagonals in lower matrix
4 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Hi, I have a matrix which I will take the sum over the diagonals in the lower matrix. So for example my matrix A=rand(4,4); the result I want is following vector
P=[sum(diag(A)); sum(diag(A,-1)); sum(diag(A,-2)); sum(diag(A,-3))]
My matrix is much larger, how can this be done without looping?
0 commentaires
Réponses (3)
Jan
le 25 Fév 2017
Modifié(e) : Jan
le 25 Fév 2017
Why do you prefer a solution without a loop?
function speedtest
A = rand(1000, 1000);
tic
for k = 1:20
P = test1(A);
end
toc
tic
for k = 1:20
P = test2(A);
end
toc
function P = test1(A)
rowdest = toeplitz(1:size(A, 1), [1, repelem(size(A, 1)+1, size(A, 2)-1)]);
P = accumarray(rowdest(:), A(:));
P = P(1:end-1);
function P = test2(A)
n = size(A, 1);
P = zeros(n, 1);
for k = 1:n
P(k) = sum(diag(A, 1-k));
end
Matlab 2016b/64, Win7, Core2Duo:
Elapsed time is 1.139792 seconds. % Toeplitz
Elapsed time is 0.182293 seconds. % Loop
I could not estimate, if the overhead for the loops or for creating the large index matrix are more expensive. But this short test seems, like the loop is efficient.
3 commentaires
Jan
le 27 Fév 2017
@Lenovo: I share your preference for smart commands and clever solutions. This dull loop does not really satisfy me. But it is simple and fast.
Guillaume
le 27 Fév 2017
The dull loop is also the simplest to understand, which I'd actually value over speed and conciseness. It's immediately clear what it does without having to do any mental gymnastic.
Another version of the loop, in my opinion even clearer (albeit probably slightly slower):
arrayfun(@(d), sum(diag(A, 1-d)), 1:size(A, 1))
Guillaume
le 25 Fév 2017
A = reshape(1:30, 5, 6) %demo data
rowdest = toeplitz(1:size(A, 1), [1, repelem(size(A, 1)+1, size(A, 2)-1)]);
P = accumarray(rowdest(:), A(:));
P = P(1:end-1)
2 commentaires
Stephen23
le 25 Fév 2017
Or without repelem:
>> A = randi(9,4,4)
A =
8 1 6 8
4 2 1 1
3 9 3 1
4 9 4 2
>> X = toeplitz(2:1+size(A,1),[2,ones(1,size(A,2)-1)]);
>> V = accumarray(X(:),A(:));
>> V = V(2:end)
V =
15
17
12
4
Jan
le 25 Fév 2017
Modifié(e) : Jan
le 25 Fév 2017
@Guillaume: Your solution is nice and Matlabish. I could not predict, if it is faster or slower than a simple loop, therefore I tried it.
After the measurement, I assume the creation of the large index matrix needs more time than the loop overhead costs.
Andrei Bobrov
le 25 Fév 2017
Modifié(e) : Andrei Bobrov
le 28 Fév 2017
P = sum(spdiags(A.',0:size(A,1)-1)).';
Voir également
Catégories
En savoir plus sur Creating and Concatenating Matrices dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!