Logical indexing using a vector
I have vector A = [2 3 1] and matrix
B = [0 1 2; 3 4 5; 6 7 8];
I would like to be able to sum values in B using elements in A as logical indexers(start and end value). More specifically, I would want my code to perform these actions :
sum(B(1:1,1), sum(B(1:2,2), sum(B(1:3,3)) as to obtain the final vector C, such that
C = [3 12 2]
I have a large number of data, so I would like to avoid using for loops as they seem to slow down the code considerably.
Thanks in advance,
I think this is what you're after:
t = arrayfun(@(n)sum(B(1:A(n),n),1),1:numel(A)) t = 11 15 6
A = 2 3 1 B = 8 1 6 3 5 7 4 9 2
I'm assuming you want the column numbers to be increasing, while the row number may vary.
First, a correction. A can't be used directly for logical indexing because it is not a vector of logical (Boolean) values. What you are referring to is called linear indexing. This is where normal index values of 1 to the number of elements index the array as if it were a vector.
Here is one way you might solve your problem if A is actually 1:size(B,1):
B = [0 1 2;3 4 5;6 7 8]; C = sum(triu(B),1)
For a more general case a for loop may be pretty fast provided that you preallocate properly. But you can also use arrayfun, which is just a for loop in disguise (and even slower in many cases):
A = [2 3 1]; B = [0 1 2;3 4 5;6 7 8]; C = arrayfun(@(x)sum(B(1:x,x)),A)
None of this uses linear indexing because your A values describe how to index in to both the rows and columns of B. One can use sub2ind to easily convert to linear indices, but this can be cumbersome in usage, e.g.:
A = [2 3 1]; B = [0 1 2;3 4 5;6 7 8]; C = arrayfun(@(x)sum(B(sub2ind(size(B),1:x,x+zeros(1,x)))),A)
Alternative answer which uses bsxfun to create a mask for the values that will be summed:
C = sum(B.*bsxfun(@le, (1:size(B,1)), A(:)).');
C=cumsum(B); C=C( sub2ind(size(B),A,1:size(B,1)) ),