Transformación de datos

Hasta ahora hemos aprendido a importar datos, identificar las características de un marco de datos y recodificar sus variables si es necesario. A partir de ahora empezaremos a explorarlas más a fondo y aprenderemos a transformarlas con el objetivo de resumir la información que buscamos. Para ello será imprescindible conocer dplyr, probablemente el paquete más utilizado en la transformación de datos con R. Como veis en la imagen de la derecha (figura 1), el icono del paquete son unas tenazas, que es una forma de representar qué hacen la mayoría de las funciones que contiene el paquete. En inglés, esto se conoce como data wrangling: pelearse con los datos y atenazarlos para conseguir que tengan el aspecto que queremos.

Anteriormente ya hemos visto algunas funciones de dplyr, como tibble(), count(), glimpse(), recode() o rename(). Todas tienen, más o menos, el mismo propósito: observar los datos y transformar algunos de sus valores. Todas estas funciones tienen las características siguientes:

Figura 1: El paquete dplyr

  • 1 El acrónimo NUTS corresponde a Nomenclature des unités territoriales statistiques (Nomenclatura de las unidades territoriales estadísticas), un sistema de clasificación de las administraciones políticas estatales y regionales de la Unión Europea con fines estadísticos.

  • Figura 2: Población de las regiones NUTS

    Ejercicio 1 (Prepara los datos) Para seguir las actividades de los siguientes apartados, carga los paquetes siguientes e importa las bases de datos a R.

    library(dplyr)
    library(readr)
    library(gapminder)
    library(unvotes)
    library(sf)
    wvs <- read_rds("wvs.rds")
    nuts <- read_rds("nuts.rds")
    nuts_geo <- read_sf("nuts_geo.shp")
    nuts_mine <- read_rds("nuts_mini.rds")

    Explora brevemente el contenido con las funciones que conoces, como glimpse(), head() o names().

    wvs #nivel individual
    nuts #nivel regional
    nuts_mini #nivel regional reducida 
    nuts_geo #nivel regional mapa
    gapminder #nivel estatal
    un_roll_call_issues #votación-tema
    un_roll_calls #votación
    un_votes #votación-país

    A partir de ahora tendremos que trabajar con conjuntos de datos cada vez más grandes, y transformarlos requerirá códigos de R cada vez más sofisticados. Y esto implica tener que aplicar varias funciones de manera simultánea en el mismo objeto. Combinar funciones es una tarea poco agradable visualmente, puesto que tenemos que poner funciones dentro de otras funciones y es complicado leer un código entre tantos paréntesis. Fijémonos en el código siguiente, donde hemos aplicado varias funciones a la variable turnout del marco de datos elections, que ya hemos trabajado anteriormente. Leer esta cadena de funciones es extremadamente complicado, entre otras cosas porque tenemos que ir contando los paréntesis para saber qué argumento corresponde a cada función.

    round(mean(round(sample(elections$turnout, 4), 0)), 0)

    Por suerte, el paquete dplyr contiene dos elementos que nos aligerarán mucho el trabajo. En primer lugar, dplyr contiene lo que se denomina pipe (símbolo |>)2, herramienta que nos permite aplicar sobre el mismo objeto varias funciones de una manera mucho más intuitiva y ordenada. Lo que hace la pipe es cambiar la gramática de las funciones, de forma que nos transforma una función de varios argumentos: f(x, y) en la estructura x |> f(y). Con el sistema pipe, el código anterior quedaría de la siguiente forma:

  • 2 El atajo de teclado para crear la pipe es Cmd+Shift+M en PC y Cmd+Shift+M en Mac. También encontraréis la pipe con el formato %>%.

  • elections$turnout |> 
      sample(4) |> 
      round(0) |>
      mean() |> 
      round(0)

    Fijaos que ahora el código es mucho más fácil de leer porque la lectura es de arriba abajo, igual como cuando leemos normalmente un texto:

    El otro aspecto de las funciones de dplyr que nos facilitará mucho el trabajo es que no necesitaremos utilizar el símbolo del dólar ($) para separar el marco de datos del vector. En lugar del dólar, el marco de datos y el vector irán simplemente separados por una coma dentro de la función en cuestión. En general, las funciones de dplyr tienen las características siguientes:

    Por lo tanto, en lugar de:

    funcion(marcodatos$vector)

    en las funciones de dplyr escribiremos3:

  • 3 Cuidado, hay muchas funciones que no son del entorno tidyverse en las que no podremos usar esta lógica y tendremos que utilizar el dólar.

  • funcion(marcodatos, vector)

    La combinación de pipe y la eliminación del símbolo del dólar permiten hacer construcciones sintácticas como la siguiente, en la que en primer lugar especificamos qué marco de datos trabajaremos y a continuación iremos especificando qué vectores del marco de datos trabajaremos con cada función específica.

    marcodatos |> 
      funcion1(vector4) |> 
      funcion2(vector22, vector51) |>
      funcion(vector14)

    Poco a poco, iremos comprendiendo la enorme utilidad que tiene este sistema. Lo importante es retener que podemos ordenar las funciones para trabajar con ellas más fácilmente y poder leer más cómodamente el contenido. Si queréis ver otro ejemplo, todavía más práctico, observad el desplegable siguiente: Nuestro día a día en una pipe.

    Nuestro día a día en una pipe

    Nuestro día a día no deja de ser un cúmulo de acciones encadenadas. Si las tradujéramos a código de R, sin una pipe la descripción sería más o menos de la siguiente forma:

    ir_universidad(coger_transporte(ropa(salir_de la_cama(despertador(yo,
    hora = "7:30"), lado = "derecha"), pantalones = TRUE, camisa = TRUE), 
    bus = TRUE, metro = FALSE), clase_datos = FALSE, bar = TRUE)

    El código anterior es bastante complicado de leer. Ahora comprobamos cómo quedaría exactamente el mismo código pero con el sistema pipe:

    yo |> 
      despertador(hora = "7:30") |> 
      salir_de la_cama(lado = "derecho") |> 
      ropa(pantalones = TRUE, camisa = TRUE) |> 
      coger_transporte(bus = TRUE, metro = FALSE) |> 
      ir_universidad(clase_datos = FALSE, bar = TRUE)

    El ejemplo está inspirado en las fuentes siguientes: aquí y aquí.