Reputation: 123
Apologies if this is a relatively basic question - I'm still a bit new to programming, and particularly Matlab. Essentially I want to create 4940x1 column vector where each term is equal to the sum of a 4940x4940 square matrix's corresponding row. So far, easy enough.
However, I would like each row to have a series of terms deleted from the sum, specifically the first 26 terms of the row for the first 26 rows, the 2nd 26 terms (i.e. terms 27-52) for the 2nd row, etc etc until you get to the 190th set of 26 terms (i.e. 4940,4915:4940) for the last 26 rows. I'm not sure if I'm explaining this well, so perhaps best illustrated with a magic 4 matrix :
A =
16 3 2 13;
5 10 11 8;
9 6 7 12;
4 15 14 1
In addition to calculating the sum of each row, I would like to subtract 1,1:2 (i.e. 34-16-3) from row 1, 2,1:2 from row 2 (i.e. 34-5-10), 3,3:4 from row 3 (i.e. 34-7-12) and 4,3:4 from row 4 (34-14-1).
Grateful for any help here!
Upvotes: 2
Views: 106
Reputation: 112689
For the sum removing some elements, you can easily create a mask (with blkdiag
) to indicate which elements are zeroed:
%// Total sum:
s1 = sum(A, 2);
%// Sum removing elements:
m = size(A, 1);
n = 26;
c = repmat({true(26)}, m/n, 1);
s2 = sum(A.* ~blkdiag(c{:}), 2)
Upvotes: 1
Reputation: 1320
Multiply the matrix elementwise with the following matrix:
M = 1-kron(eye(4940/26),ones(26));
In this way, you multiply the elements that you do not want to count with 0 and the others with 1.
You can now just sum the result as you did before: sum(.,2)
.
For the magic example, you get M =
0 0 1 1
0 0 1 1
1 1 0 0
1 1 0 0
and A .* M =
0 0 2 13
0 0 11 8
9 6 0 0
4 15 0 0
and sum(A.*M, 2) =
15
19
15
19
I updated the answer, taking the first comment of Divakar into consideration. Concerning the speed, see the additional comments below.
Upvotes: 0
Reputation: 221574
bsxfun
based summing and reshaping approach -
sublen = 26; %// subset length
nrows = size(A,1); %// number of rows in input matrix
nsubs = nrows/sublen; %// number of subsets
idx1 = bsxfun(@plus,[1:sublen]',[0:sublen-1]*nrows);%//'# starting block indices
idx2 = bsxfun(@plus,idx1(:),[0:nsubs-1]*(nrows*sublen+sublen));%// all block indices
exclude_sum = sum(A(reshape(idx2,sublen,sublen,[])),2); %// block elements summed
%// (these would be subtracted from the wholesome sum)
out = sum(A,2) - exclude_sum(:); %// desired output
This approach seems to be 6-7x
faster than an improved version of the other kron
based approach.
Here are the runtimes - https://ideone.com/vZRRfe
Upvotes: 1