lunes, 28 de marzo de 2016

Transformar variables usando Box-Cox

Si se tiene un data set con variables que no tienen una distribución normal, y se quiere transformar esas variables para obtener mayor información de ellas, una forma es usar la transformación de box-cox, que busca un valor "lambda" para elevar la variable hasta encontrar la desviaciones estándar más cercana a cero, y así obtener una nueva variable con una distribución más "normal". Para detalles de box-cox ver referencia.

Conceptualmente las transformaciones quedan así:












 y el data set queda así:






El script debajo sigue estos pasos:

1. Identifica si una variable tiene distribución normal usando la asimetría y el coeficiente de variación. Si la asimetría es menor a -1 o mayor a 1, y el coeficiente de variación es mayor a 1, entonces la variable no tiene una distribución normal y requiere una transformación.

2. Luego de identificar la variable que no tiene una distribución normal, calcula el valor lambda donde elevando la variable a ese valor se obtiene una distribución normal, y crea una nueva variable con el prefijo "BoxCox_"



# LIBRERIA Y DATOS
# -----------------------------------------------------------------------
library(MASS)
library(forecast)
library(e1071)  
df <- Boston 
v  <- names(df[,sapply(df, class)=="numeric"])

# TRANSFORMACION BOX-COX
# ------------------------------------------------------------------------------
for (ii in 1:length(v)){
  asimetria       <- skewness(df[,v[ii]])
  coef.variacion  <- sd(df[,v[ii]]) / mean(df[,v[ii]]) 
  
  if ( (asimetria < -1 | asimetria > 1) & coef.variacion > 1){
    print(paste("transformando variable: ",v[ii]))
    df$bc_tmp     <- BoxCox(df[,v[ii]],BoxCox.lambda(df[,v[ii]]))
    names(df)[names(df)=="bc_tmp"] <- paste("BoxCox_", v[ii], sep = "")
  }
}


7 comentarios:

  1. hola que tal cuando replico tus scripts con otra data me sale error, podría enviarte un correo con mi caso?

    ResponderEliminar
  2. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  3. Respuestas
    1. Lambda es un valor buscado para cada variable, en este caso (usando la libreria forecast) itera desde -2 hasta 2, con intervalos de 0.1. Para mas detalles, ver referencia al final de la nota.

      Eliminar
  4. Buenos días, te agradezco mucho este post y quería comentarte una duda que me surge a mi. Al meter mis datos y correr el script me aparece el siguiente error:

    Error in is.data.frame(x) :
    (list) object cannot be coerced to type 'double'
    In addition: Warning message:
    In mean.default(x) : argument is not numeric or logical: returning NA

    ¿Qué puede estar pasando?
    Muchas gracias de antemano!

    ResponderEliminar
  5. Buenos días, una pregunta. Una vez transformados los datos es necesario hacer una estandarización usanto scale()? Se hace después de la transformación? No es necesario hacerla aunque las escalas sean diferentes? Gracias

    ResponderEliminar