2018-10-14

Importar ficheros comprimidos en R con readr

Title

Problema

Queremos importar ficheros comprimidos en R.

Solución

Empleamos el paquete readr que descomprime automáticamente los siguientes tipos de ficheros: gz, .bz2, .xz, o .zip. Podemos emplearlo con la read_delim o los casos especiales read_csv, read_csv2 o read_tsv. En nuestro ejemplo utilizamos el fichero title.ratings.tsv.gz.

library(readr)
df_ratings <- read_tsv('title.ratings.tsv.gz', na = "\\N", quote = '')
df_ratings %>% head()
También podemos indicar la dirección del fichero y automáticamente descargará y descomprimirá el mismo.

df_ratings <- read_tsv('https://datasets.imdbws.com/title.ratings.tsv.gz', na = "\\N", quote = '')
df_ratings %>% head()

Resultados

# A tibble: 6 x 3
  tconst    averageRating numVotes
                   
1 tt0000001           5.8     1423
2 tt0000002           6.4      168
3 tt0000003           6.6     1016
4 tt0000004           6.4      100
5 tt0000005           6.2     1713
6 tt0000006           5.5       88

Entradas relacionadas

Referencias

2018-10-06

Generar direcciones de correo aleatorias en R

Title

Problema

Necesitamos crear un vector con direcciones de correo aleatorias.

Solución

Hay múltiples opciones, ofrezco dos con los paquetes generator y stringi.

  • generator
  • library(generator)
    # Ejemplo 1: 10 direcciones
    set.seed(1977)
    r_email_addresses(10)
    # Ejemplo 2: Añadir a data frame
    library(dplyr
    set.seed(1977)
    mtcars %>% mutate(email = r_email_addresses(n())) %>% head(10)
    
  • stringi
  • Opción más verbosa, pues concatenamos dos cadenas de texto aleatorias separadas por una arroba. Ganamos en flexibilidad pues podemos escoger la longitud de las mismas.

    library(stringi)
    set.seed(1977)
    paste0(stringi::stri_rand_strings(10, 5),
           "@",
           stringi::stri_rand_strings(10, 5))
    set.seed(1977)
    mtcars %>% mutate(email = paste0(
      stringi::stri_rand_strings(n(), 5),
      "@",
      stringi::stri_rand_strings(n(), 5)
    )) %>% head(10)
    

    Resultados

    [1] "rdkvi@kfjaul.myo"      "qpm@bxvqkrtl.fhk"      "aedcq@a.ruc"          
     [4] "xi@l.wkp"              "bhk@obcjyzdi.tda"      "da@qksrfahvup.yel"    
     [7] "ahjq@lg.gmo"           "agcmyp@i.itc"          "rutfv@ponbi.jtm"      
    [10] "yeaxlbsko@ntlvkfe.fsg"
    
        mpg cyl  disp  hp drat    wt  qsec vs am gear carb                     email
    1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4          rdkvi@kfjaul.myo
    2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4          qpm@bxvqkrtl.fhk
    3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1               aedcq@a.ruc
    4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1                  xi@l.wkp
    5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2          bhk@obcjyzdi.tda
    6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1         da@qksrfahvup.yel
    7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4               ahjq@lg.gmo
    8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2              agcmyp@i.itc
    9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2           rutfv@ponbi.jtm
    10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4     yeaxlbsko@ntlvkfe.fsg
    

    Entradas relacionadas

    2018-09-27

    Celda de esquina con etiqueta doble en Excel

    Title

    Problea

    Deseamos crear una celda de esquina con etiqueta doble, tal como la celda A1 en el siguiente ejemplo.

    Solución

    1. En la celda deseada insertamos varios espacios antes de la primera palabra de la etiqueta, presionamos ALT+ENTRAR para insertar el salto de línea y escribimos la siguiente etiqueta
    2. Seleccionamos la celda y abrimos el cuadro de diálogo Formato de celdas presionando Ctrl+1. En Borde clic en la línea diagonal descendente.
    3. Cambiamos el color de relleno y de la fuente si fuera necesario.

    Entradas relacionadas

    2018-09-25

    Encabezados de columna en diagonal con Excel

    Title

    Problea

    Deseamos formatear los encabezados de las columnas de manera que aparezcan en diagonal, tal como en el siguiente ejemplo.

    Solución

    1. Partimos de una tabla sin formatear
    2. Seleccionamos los encabezados y abrimos el cuadro de diálogo Formato de celdas presionando Ctrl+1. En orientación seleccionamos 45 grados
    3. Alternativamente podemos hacer clic en Orientación, y seleccionar Ángulo ascendente.
    4. Cambiamos el estilo de los bordes y ajustamos el ancho de la columna
    5. Cambiamos el color del relleno y de la fuente

    Entradas relacionadas

    2018-09-23

    Gráficos de An Introduction to Statistical Learning - Figura 2.6.

    Title

    Gráfico a replicar

    Continuamos con la serie iniciada sobre la creación de gráficos del libro An Introduction to Statistical Learning. En esta ocasión replicaremos los gráficos de la figura 2.6. Utiliza el conjunto de datos Income2 (renta). El gráfico representa los valores observados de renta (en miles de dólares) en función de los años de educación y la antigüedad de 30 individuos. Los puntos rojos representan los valores observados para esas tres variables. La superficie amarilla representa un modelo de suavizado con thin-plate spline. En este caso no hay líneas verticales negras que representaban el error asociado con cada observación, pues la superficie thin-plate spline se adapta perfectamente a los datos.

    Solución

    Como utilizamos el paquete mgcv que se utiliza para regresión no para interpolación por lo que tenemos que ajustarlo para que la superficie thin plate spline pase por todos los puntos.

    1. Desactivamos la aproximación de bajo rango que utiliza bs = 'tp' estableciendo el parámetro k con el número exacto de datos de la muestra.
    2. xt <- unique(income_2[c("Education", "Seniority")]) 
      nrow(xt)
      
      [1] 30
      
    3. Empleamos sp = 0 para desactivar la penalización de la spline.

  • Primera aproximación
  • model <- gam(Income ~ s(Education, Seniority, k = 30, sp = 0),
                               data = income_2)
    x <- range(income_2$Education)
    x <- seq(x[1], x[2], length.out=30)
    y <- range(income_2$Seniority)
    y <- seq(y[1], y[2], length.out=30)
    z <- outer(x, y, 
               function(Education,Seniority)
                         predict(model, data.frame(Education,Seniority)))
    p <- persp(x, y, z, theta = 30, phi = 30, 
               col = "yellow", expand = 0.5, shade = 0.2, 
               xlab = "Education", ylab = "Seniority", zlab = "Income")
    obs <-  trans3d(income_2$Education, income_2$Seniority, income_2$Income, p)
    pred <-  trans3d(income_2$Education, income_2$Seniority, fitted(model), p)
    points(obs, col = "red", pch = 16)
    segments(obs$x, obs$y, pred$x, pred$y)
    
    Como se puede apreciar en el gráfico, hemos eliminado los errores y se adapta perfectamente a los puntos. Sin embargo, se puede apreciar que la superficie es muy ondulada pues spline es isotrópica o radial. Como dos variables difieren considerablemente en escala, necesitaremos estandarizarlas.

    with(income_2, plot(Education, Seniority, asp = 1))
    
    Las estandarizamos y representamos nuevamente:

    xt_scaled <- scale(xt)
    dat <- data.frame(xt_scaled, Income = income_2$Income)
    with(dat, plot(Education, Seniority, asp = 1))
    
    # Ajustamos el modelo a los datos escalados
    interpolation_model <- gam(Income ~ s(Education, Seniority, k = 30, sp = 0),
                               data = dat)
    # Creamos las coordenadas para el gráfico
    x <- range(dat$Education)
    x <- seq(x[1], x[2], length.out=30)
    y <- range(dat$Seniority)
    y <- seq(y[1], y[2], length.out=30)
    z <- outer(x, y, 
               function(Education,Seniority)
                         predict(interpolation_model, data.frame(Education,Seniority)))
    
    # Volvemos a transformar las coordenadas x e y a su escala original.
    # No es necesario transformar los valores esperados (predicted values, pred)
    scaled_center <- attr(xt_scaled, "scaled:center")
    scaled_scale <- attr(xt_scaled, "scaled:scale")
    xx <- x * scaled_scale[1] + scaled_center[1]
    yy <- y * scaled_scale[2] + scaled_center[2]
    
    # Usamos `xx`, `yy` y `z`
    p <- persp(xx, yy, z, theta = 30, phi = 30,
               col = "yellow",expand = 0.5, shade = 0.2,
               xlab = "Education", ylab = "Seniority", zlab = "Income")
    obs <-  trans3d(income_2$Education, income_2$Seniority, income_2$Income, p)
    pred <-  trans3d(income_2$Education, income_2$Seniority, fitted(interpolation_model), p)
    points(obs, col = "red", pch = 16)
    segments(obs$x, obs$y, pred$x, pred$y)
    

    Entradas relacionadas

    Referencias

    2018-09-15

    Gráficos de An Introduction to Statistical Learning - Figura 2.5.

    Title

    Gráfico a replicar

    Continuamos con la serie iniciada sobre la creación de gráficos del libro An Introduction to Statistical Learning. En esta ocasión replicaremos los gráficos de la figura 2.5. Utiliza el conjunto de datos Income2 (renta). El gráfico representa los valores observados de renta (en miles de dólares) en función de los años de educación y la antigüedad de 30 individuos. Los puntos rojos representan los valores observados para esas tres variables. La superficie amarilla representa un modelo de suavizado con thin-plate spline. En este caso . Las líneas verticales negras representan el error asociado con cada observación.

    Solución

    Prácticamente idéntica a las dos entradas anteriores, con la diferencia de que en lugar de la función loess o lm para ajustar un modelo lineal, empleamos otros modelos de suavizado con splines, con diferentes parámetros (tensor product, o bivariate).

  • Tensor product
  • Bivariate
  • income_2 <- read.csv("http://www-bcf.usc.edu/~gareth/ISL/Income2.csv")
    library(mgcv)
    model1 <- gam(Income ~ te(Education, Seniority, bs = "tp"), data = income_2) # tensor product
    model1 <- gam(Income ~ s(Education, Seniority, bs = "tp"), data = income_2) # bivariate
    x <- range(income_2$Education)
    x <- seq(x[1], x[2], length.out=30)
    y <- range(income_2$Seniority)
    y <- seq(y[1], y[2], length.out=30)
    z <- outer(x,y,
               function(Education,Seniority)
                         predict(model1, data.frame(Education,Seniority)))
    p <- persp(x,y,z, theta=30, phi=30,
               col="yellow",expand = 0.5,shade = 0.2,
               xlab="Education", ylab="Seniority", zlab="Income")
    obs <- trans3d(income_2$Education, income_2$Seniority,income_2$Income,p)
    pred <- trans3d(income_2$Education, income_2$Seniority,fitted(model1),p)
    points(obs, col="red",pch=16)
    segments(obs$x, obs$y, pred$x, pred$y)
    

    Entradas relacionadas

    Referencias

    Nube de datos