Vectorization loop with repeated indexes

I have a vector of indices that contains duplicate values:

 IN <- c(1, 1, 2, 2, 3, 4, 5)     

      

I would like to use these indices to subtract two vectors:

ST <- c(0, 0, 0, 0, 0, 0, 0)
SB <- c(1, 1, 1, 1, 1, 1, 1)

      

However, I would like to do the subtraction in "order" so that after subtracting the first index values ​​(0, 1), the second expression "works" with the first subtraction. I would like to get a vector FN that looks like this:

c(-2, -2, -1, -1, -1, 0, 0)

      

It's easy enough to do this in a for loop:

for(i in seq_along(IN)){
  ST[IN[i]] <- ST[IN[i]] - SB[IN[i]]
}

      

But I need to run this loop many times on long vectors and it can take many hours. Is there a way to vectorize this task and avoid the for loop? Perhaps using the data.table technique?

+3


source to share


2 answers


Of course with data.table, this is

library(data.table)
DT = data.table(ST)
mDT = data.table(IN, SB)[, .(sub = sum(SB)), by=.(w = IN)]
DT[mDT$w, ST := ST - mDT$sub ]

   ST
1: -2
2: -2
3: -1
4: -1
5: -1
6:  0
7:  0

      



Or with base R:

w = sort(unique(IN))
ST[w] <- ST[w] - tapply(SB, IN, FUN = sum)
# [1] -2 -2 -1 -1 -1  0  0

      

+4


source


Here's an option using aggregate

R in base:

ag <- aggregate(.~IN, data.frame(IN, ST[IN]-SB[IN]), sum)
replace(ST, ag[,1], ag[,2])

#[1] -2 -2 -1 -1 -1  0  0

      



OR using xtabs

:

d <- as.data.frame(xtabs(B~A, data.frame(A=IN, B=ST[IN]-SB[IN])))
replace(ST, d[,1], d[,2])

      

+2


source







All Articles