user2883477
user2883477

Reputation: 153

Round values while preserving the sum WITH specific intervals

I want to round a vector of values WHILE preserving the sum AND taking into account an interval number.

Let´s say I have a vector:

vector <- c(0.2, 1.8, 40.4, 10.6, 0.5, 1.5)

Now I want to round the numbers while preserving their sum of 55. This function does just that:

smart.round <- function(x) {
   y <- floor(x)
   indices <- tail(order(x-y), round(sum(x)) - sum(y))
   y[indices] <- y[indices] + 1
   y
}

smart.round(vector)
[1] 0 2 40 11 0 2

BUT I want to also take into account an interval that an user has defined. Let´s say 5. This function does just that:

mround <- function(x,base){ 
   base*round(x/base) 
}  

mround(vector, 5)
[1] 0 0 40 10 0 0

Now I want to combine both functions. But I cant figure out how. Basically I would like the output to be:

vector <- c(0.2, 1.8, 40.4, 10.6, 0.5, 1.5) 

combined.round(vector, 5)
[1] 0 5 40 10 0 0

(as 1.8 is closest to 5 and atleast one value needs to be rounded to 5 to preserve the sum of 55) Sum is 55 and every number has interval of 5 in the required output.

Any help or suggestions are much appreciated!

Upvotes: 1

Views: 222

Answers (1)

Ihsan Kahveci
Ihsan Kahveci

Reputation: 53

I am not the one who found the solution but I guess somebody has to post it for everyone. It's a beautiful solution, thanks! @Miff

smart.round <- function(x, interval = 1){ 
  x <- x / interval 
  y <- floor(x) 
  indices <- tail(order(x-y), round(sum(x)) - sum(y)) 
  y[indices] <- y[indices] + 1 
  return(y * interval)
} 

Upvotes: 1

Related Questions