jake_matlab_novice
jake_matlab_novice

Reputation: 123

Summing rows, but with different terms in every row deleted

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

Answers (3)

Luis Mendo
Luis Mendo

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

MeMyselfAndI
MeMyselfAndI

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

Divakar
Divakar

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

Related Questions