[R] sum portions of a vector

Marc Schwartz marc_schwartz at me.com
Mon Dec 10 22:39:00 CET 2012


On Dec 10, 2012, at 3:29 PM, Marc Schwartz <marc_schwartz at me.com> wrote:

> 
> 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



Ack, copied and pasted the above with a typo. Same result, but should be:

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

Regards,

Marc




More information about the R-help mailing list