lunes, 27 de abril de 2020

R en español: Redondear un vector de números sin alterar la suma total del vector

En ocasiones necesitamos redondear pero deseamos mantener ciertas propiedades. En este caso, existe una función para R que permite redondear una serie de números sin que se altere la suma total de la misma.

Por ejemplo, supongamos que tenemos el siguiente vector:

x = c(1.5, 1.2, 1.3)

La suma total de este vector es 4, pero al momento de redondear es probable obtener como resultado este vector:

x = c(2, 1, 1)

O bien, este otro:

x = c(1, 1, 1)

Al trabajar con únicamente 3 números es fácil resolver el dilema de qué hacer para redondear respetando la suma total del vector (es decir, 4), sin embargo, al trabajar con mucho más números el problema se torna un poco más complicado.

La manera más simple de resolver esto y de evitar el roundoff error es con la siguiente función:

smart.round <- function(x) {
  y <- floor(x)
  indices <- tail(order(x-y), round(sum(x)) - sum(y))
  y[indices] <- y[indices] + 1
  y
}
v
# [1] 2.655087 3.721239 5.728534 9.082078 3.813063
sum(v)
# [1] 25
smart.round(v)
# [1] 2 4 6 9 4
sum(smart.round(v))
# [1] 25
Si lo que se desea es redondear respetando además un cierto número de decimales, se puede usar esta otra función:

smart.round <- function(x, digits = 0) {
  up <- 10 ^ digits
  x <- x * up
  y <- floor(x)
  indices <- tail(order(x-y), round(sum(x)) - sum(y))
  y[indices] <- y[indices] + 1
  y / up
}
Este código y más detalles sobre el mismo pueden consultarse en:
https://stackoverflow.com/questions/32544646/round-vector-of-numerics-to-integer-while-preserving-their-sum

No hay comentarios:

Publicar un comentario

R en Español: Obtener nombres de renglones con funcion row.names

Si deseo obtener los nombres de los renglones de mi dataframe puedo utilizar la función row.names de la paquetería básica de R y RStudio. ...