[R] sum portions of a vector

Marc Schwartz marc_schwartz at me.com
Mon Dec 10 22:29:42 CET 2012


On Dec 10, 2012, at 2:52 PM, David Winsemius <dwinsemius at comcast.net> wrote:

> 
> On Dec 10, 2012, at 11:29 AM, Sam Steingold wrote:
> 
>> How do I sum portions of a vector into another vector?
>> E.g., for
>> --8<---------------cut here---------------start------------->8---
>>> vec <- 1:10
>>> breaks <- c(3,8,10)
>> --8<---------------cut here---------------end--------------->8---
>> I want to get a vector of length 3 with content
>> --8<---------------cut here---------------start------------->8---
>> 6 = 1+2+3
>> 30 = 4+5+6+7+8
>> 19 = 9+10
>> --8<---------------cut here---------------end--------------->8---
>> Obviously, I could write a loop, but I would rather have a vectorized
>> version.
> 
> > tapply(vec, cut(vec, breaks=c(-Inf, breaks), include.lowest=TRUE), sum)
> [-Inf,3]    (3,8]   (8,10]
>       6       30       19


One gotcha there David, as I think you were on the right track earlier with findInterval(). The result with this approach, using cut(), takes advantage of the idiosyncrasy of Sam's example, which uses a sorted vector (1:10) that is equivalent to the indices of the same vector (1:10).  

If Sam really is using 'breaks' as the indices into 'vec' and not as ranges for the values to be summed, as cut() does, then findInterval() works:

set.seed(1)
vec2 <- sample(vec)

> vec2
 [1]  3  4  5  7  2  8  9  6 10  1


[-Inf,3] = 3+2+1 = 6
(3,8] = 4+5+7+8+6 = 30
(8,10] = 9+10 = 19

> tapply(vec2, cut(vec2, breaks=c(-Inf, breaks), include.lowest=TRUE), sum)
[-Inf,3]    (3,8]   (8,10] 
       6       30       19 


as compared to:


3+4+5 = 12
7+2+8+9+6 = 32
10+1 = 11

> as.vector(sapply(split(vec2, findInterval(seq(along = vec), breaks + 1)), sum))
[1] 12 32 11


Regards,

Marc




More information about the R-help mailing list