 ken -4 years ago 46
R Question

# Vectorize loop with repeating indices

I have a vector of indices that contains repeating values:

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

I would like to uses 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" such that after subtraction of the first index values (0, 1), the second substraction would "build off" the first subtraction. I would like to end up with a vector FN that looks like this:

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

This is easy enough to do 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 this can take many hours. Is there any way to vectorize this task and avoid a for loop? Maybe using a data.table technique? Frank
Answer Source

Sure, with data.table, it's

``````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)
#  -2 -2 -1 -1 -1  0  0
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download
Latest added