If you pre-calculate all the intervals and then only calculate the remainder in each interval for each value, I think you can do this safely in a vectorised fashion without requiring branching. This will then also be extendable to adding as many cutoffs and rates as required without having to adjust the body of the function.
propmult <- function(x, rate, coff) {
spot <- findInterval(x, coff)
base <- cumsum(rate * c(diff(coff), 0))[spot-1]
base + ((x - coff[spot]) * rate[spot])
}
Comparing results with other answer:
propmult(my_data$Var_1, rate = c(0, 0.02, 0.03, 0.05), coff = c(0, 100, 1000, 2000))
##[1] 198.0 33.0 5.0 24.0 13.0 18.0 25.5 73.0
map_dbl(my_data$Var_1, foo)
##[1] 198.0 33.0 5.0 24.0 13.0 18.0 25.5 73.0
As a side benefit, it should also be quick to run on huge data if that is a concern:
datbig <- my_data[rep(1:8,1e6),]
nrow(datbig)
# 8 million rows - 8,000,000 - to test it out
system.time({ map_dbl(datbig$Var_1, foo) })
## user system elapsed
## 5.049 0.092 5.140
system.time({propmult(datbig$Var_1, rate = c(0, 0.02, 0.03, 0.05), coff = c(0, 100, 1000, 2000))})
## user system elapsed
## 0.138 0.000 0.138