2  Primeros pasos con tidyverse

2.1 Presentación

2.2 Comprendiendo nuestra data

La primera etapa del Análisis Exploratorio de Datos (EDA) en Machine Learning se centra en los pasos básicos con tidyverse, ya que este ecosistema de herramientas facilita la importación, organización y transformación de la información. En este punto, resulta esencial familiarizarnos con la estructura de los datos, reconocer las variables disponibles y aplicar operaciones que nos permitan manipular y preparar la base de forma eficiente. Este proceso no solo brinda una comprensión profunda de la data, sino que también sienta los cimientos para un análisis riguroso y para el éxito de las fases posteriores de modelamiento.

Te sugiero ver este video introductorio sobre el Tidyverse:

Abrimos la librería tidyverse:

library(tidyverse)

dplyr es un paquete del Tidyverse que sirve para manipular tablas y transformarlas. Tiene una amplia gama de verbos con los cuales podemos realizar las tareas más recurrentes de la manipulación de datos.

2.2.1 Importación de archivos

Podríamos abrir este archivo con la función read_xlsx():

library(readxl)
data<-read_xlsx("data/CPI.xlsx")

Visualizamos la data y solicitamos que nos diga la clase:

data
# A tibble: 1,086 × 5
   country               year iso3  region cpi_score
   <chr>                <dbl> <chr> <chr>      <dbl>
 1 Afghanistan           2022 AFG   AP            24
 2 Albania               2022 ALB   ECA           36
 3 United Arab Emirates  2022 ARE   MENA          67
 4 Angola                2022 AGO   SSA           33
 5 Argentina             2022 ARG   AME           38
 6 Armenia               2022 ARM   ECA           46
 7 Australia             2022 AUS   AP            75
 8 Austria               2022 AUT   WE/EU         71
 9 Azerbaijan            2022 AZE   ECA           23
10 Bahamas               2022 BHS   AME           64
# ℹ 1,076 more rows
class(data)
[1] "tbl_df"     "tbl"        "data.frame"
Nota

Un tibble es una versión moderna del dataframe en R, parte del tidyverse, diseñado para facilitar el trabajo con datos tabulares.

Exploración del dataset y configuración de variables

Vemos la estructura rápidamente:

str(data)
tibble [1,086 × 5] (S3: tbl_df/tbl/data.frame)
 $ country  : chr [1:1086] "Afghanistan" "Albania" "United Arab Emirates" "Angola" ...
 $ year     : num [1:1086] 2022 2022 2022 2022 2022 ...
 $ iso3     : chr [1:1086] "AFG" "ALB" "ARE" "AGO" ...
 $ region   : chr [1:1086] "AP" "ECA" "MENA" "SSA" ...
 $ cpi_score: num [1:1086] 24 36 67 33 38 46 75 71 23 64 ...

Al ejecutar names() sobre un conjunto de datos, se nos devuelve un vector con los nombres de todas las columnas en el orden en que aparecen.

names(data)
[1] "country"   "year"      "iso3"      "region"    "cpi_score"
Tip

Antes de proseguir con el análisis exploratorio de datos, es fundamental que comprendas claramente qué representan las filas y las columnas en tus datos.

Corroboramos que el score del AML esté adecuadamente configurado.

class(data$cpi_score)
[1] "numeric"

De acuerdo, podemos proseguir.

Examinemos la base original. Vamos a editar la tabla con diversos verbos de dplyr.

2.2.2 Select()

La función select() es utilizada para seleccionar o excluir columnas de un data frame o tibble en R. Va más allá de simplemente escoger columnas por nombre, ya que permite una amplia gama de criterios y operaciones.

Funcionamiento básico:

  • Entrada: Un data frame o tibble y un conjunto de nombres de columnas o criterios para seleccionar columnas.

  • Salida: Un objeto de la misma clase que el de entrada (data frame o tibble) que contiene solo las columnas seleccionadas.

Vamos a seleccionar sólo ciertas columnas:

data1<-data |> 
  select(country, year, region, cpi_score)
data1
# A tibble: 1,086 × 4
   country               year region cpi_score
   <chr>                <dbl> <chr>      <dbl>
 1 Afghanistan           2022 AP            24
 2 Albania               2022 ECA           36
 3 United Arab Emirates  2022 MENA          67
 4 Angola                2022 SSA           33
 5 Argentina             2022 AME           38
 6 Armenia               2022 ECA           46
 7 Australia             2022 AP            75
 8 Austria               2022 WE/EU         71
 9 Azerbaijan            2022 ECA           23
10 Bahamas               2022 AME           64
# ℹ 1,076 more rows

Tener en cuenta que puedes:

  • Seleccionar por nombre

  • Seleccionar por el número de la columna

  • (Des)seleccionar colocando un “-” antes del nombre/número de columna.

  • Seleccionar un rango colocando por ejemplo 2:4 lo que significa “desde la columna 2 hasta la columna 4).

  • Puedes combinar todas las anteriores y tener más de un criterio a la vez separándolo por coma.

2.2.3 Filter()

La función filter() se utiliza para filtrar filas de un data frame o tibble en R en función de condiciones específicas, permitiendo crear un subconjunto de datos.

Al crear subconjuntos nuestros datos de forma precisa, podemos focalizar nuestro análisis, mejorar la eficiencia computacional y obtener resultados más claros y relevantes.

Características principales:

  • Condiciones múltiples: Puedes usar múltiples condiciones para filtrar tus datos. Estas se combinan utilizando operadores lógicos como & (y), | (o) y ! (no).

  • Uso de operadores de comparación: Los operadores estándar como ==, >, <, >=, <=, y != se utilizan para establecer condiciones.

  • Funciones auxiliares: dplyr proporciona funciones como between(), que pueden ser útiles para establecer condiciones. Por ejemplo, between(x, 1, 10) es equivalente a x >= 1 & x <= 10.

En este caso vamos a seleccionar aquellos países cuya medición es del año 2022.

data2<-data1 %>%                   
  filter(year==2022)
data2
# A tibble: 181 × 4
   country               year region cpi_score
   <chr>                <dbl> <chr>      <dbl>
 1 Afghanistan           2022 AP            24
 2 Albania               2022 ECA           36
 3 United Arab Emirates  2022 MENA          67
 4 Angola                2022 SSA           33
 5 Argentina             2022 AME           38
 6 Armenia               2022 ECA           46
 7 Australia             2022 AP            75
 8 Austria               2022 WE/EU         71
 9 Azerbaijan            2022 ECA           23
10 Bahamas               2022 AME           64
# ℹ 171 more rows

2.2.4 Arrange()

Se utiliza para ordenar (o reordenar) un data frame o tibble según una o más columnas.

Funcionamiento básico:

  • Ordenación simple: Si proporcionas una columna a arrange(), ordenará el data frame en función de esa columna en orden ascendente por defecto.

  • Ordenación descendente: Si deseas ordenar en dirección descendente, puedes usar la función desc(). Por ejemplo: df |> arrange(desc(edad)) ordenará el data frame por la columna “edad” en orden descendente.

  • Ordenación múltiple: Puedes proporcionar múltiples columnas para ordenar, y arrange() las usará en el orden proporcionado para determinar el ordenamiento. Por ejemplo, si deseas ordenar primero por “grupo” y luego por “edad” dentro de cada grupo, usarías: df |> arrange(grupo, edad).

data3<-data2 |>    
  arrange(desc(cpi_score))
data3
# A tibble: 181 × 4
   country      year region cpi_score
   <chr>       <dbl> <chr>      <dbl>
 1 Denmark      2022 WE/EU         90
 2 Finland      2022 WE/EU         87
 3 New Zealand  2022 AP            87
 4 Norway       2022 WE/EU         84
 5 Singapore    2022 AP            83
 6 Sweden       2022 WE/EU         83
 7 Switzerland  2022 WE/EU         82
 8 Netherlands  2022 WE/EU         80
 9 Germany      2022 WE/EU         79
10 Ireland      2022 WE/EU         77
# ℹ 171 more rows

2.2.5 Mutate()

La función mutate() está diseñada para crear o modificar columnas dentro de un data frame o tibble en R. Mientras que el data frame original se mantiene inalterado, mutate() devuelve una copia con las columnas especificadas añadidas o alteradas.

En este caso vamos a crear una variable cambiando la escala del score del CPI.

En la medida original 0 representaba alta corrupción y 100 escasa corrupción. Ahora, si realizamos la operación “100 - cpi_score”, los valores cercanos a 0 tendrán poca corrupción y los cercanos a 100 alta corrupción, siendo más intuitivo.

Esta transformación puede ser útil para ajustar la interpretación de los datos a contextos donde es más intuitivo trabajar con escalas donde un número mayor indica mayor intensidad de un fenómeno (Corrupción, en este caso), dependiendo del análisis que se desea realizar.

data4<-data3 |>   
  mutate(cpi_score2=100-cpi_score) 
data4
# A tibble: 181 × 5
   country      year region cpi_score cpi_score2
   <chr>       <dbl> <chr>      <dbl>      <dbl>
 1 Denmark      2022 WE/EU         90         10
 2 Finland      2022 WE/EU         87         13
 3 New Zealand  2022 AP            87         13
 4 Norway       2022 WE/EU         84         16
 5 Singapore    2022 AP            83         17
 6 Sweden       2022 WE/EU         83         17
 7 Switzerland  2022 WE/EU         82         18
 8 Netherlands  2022 WE/EU         80         20
 9 Germany      2022 WE/EU         79         21
10 Ireland      2022 WE/EU         77         23
# ℹ 171 more rows

2.2.6 Summarise()

Se utiliza para crear resúmenes estadísticos de un data frame o tibble.

Dentro de los resúmenes puedes disponer de por ejemplo:

Medidas de tendencia central: Estas funciones describen un valor central o típico dentro de un conjunto de datos.

  • Media: mean(x)
  • Mediana: median(x)

Cómo calcularíamos la media de forma directa (tradicional)?

summary(data4$cpi_score2)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  10.00   45.00   60.50   57.02   70.25   88.00       1 
Advertencia

¿Qué significa NA´s? ¿Por qué se produce esto en una data como la de Corruption Perception Index?

Cómo lo calculamos con tidyverse?

data4 |>   
  summarise(mean(cpi_score2, na.rm = T))    
# A tibble: 1 × 1
  `mean(cpi_score2, na.rm = T)`
                          <dbl>
1                          57.0
Nota

Cuando aplicamos un summarise lo que nos devuelve es un valor o conjunto de valores. Por otro lado, el argumento na.rm = TRUE se utiliza para especificar que los valores perdidos (NA) deben ser ignorados en el cálculo. De esta forma, le indicamos a la función que proceda con la operación excluyendo dichos valores ausentes.

2.2.7 Utilizando pipe: |>

Probablemente hayas observado que hemos creado un conjunto de datos para cada verbo utilizado, lo cual en situaciones reales resultaría excesivamente repetitivo. Haciendo una analogía con la escritura de un libro, sería como si estuviéramos limitados a usar únicamente oraciones, lo cual haría el proceso tedioso.

El operador |> (pipe) en R, introducido en la versión 4.1, permite realizar operaciones en cadena, facilitando la secuencia de funciones y transformaciones en un flujo más legible y ordenado.

Es evidente que, mediante el uso del operador pipe, podemos encadenar verbos de manera fluida y evitar la creación innecesaria de objetos, ya que este operador permite que el resultado a la izquierda se convierta automáticamente en el argumento de la función a la derecha.

data |>
  select(country, year, region, cpi_score) |> 
  filter(year==2022) |> 
  arrange(desc(cpi_score)) |> 
  mutate(cpi_score2=100-cpi_score) |> 
  summarise(mean(cpi_score2, na.rm=T))  
# A tibble: 1 × 1
  `mean(cpi_score2, na.rm = T)`
                          <dbl>
1                          57.0
Advertencia

¿Qué sucede si a esta cadena de pipes le doy un nombre? ¿Cuál sería el objeto creado?

data_final<-data |>
  select(country, year, region, cpi_score) |> 
  filter(year==2022) |>
  arrange(desc(cpi_score)) |>
  mutate(cpi_score2=100-cpi_score) 

2.2.8 Agrupando con group_by()

Se utiliza para dividir un conjunto de datos en grupos según valores de una o más variables (normalmente de tipo categórica). Una vez que los datos están agrupados, es posible realizar operaciones específicas dentro de cada grupo.

data |>   
  group_by(year) |> 
  summarise(Media=mean(cpi_score, na.rm = T)) 
# A tibble: 6 × 2
   year Media
  <dbl> <dbl>
1  2017  43.1
2  2018  43.1
3  2019  43.2
4  2020  43.3
5  2021  43.3
6  2022  43.0

2.2.9 Contar con count()

Facilita el conteo de observaciones dentro de categorías específicas de una o más variables en un dataframe. Esta función agrupa el conjunto de datos por las variables especificadas y luego calcula el número de observaciones dentro de cada categoría, retornando un nuevo dataframe con las categorías y sus respectivos conteos. Es una herramienta esencial para obtener resúmenes rápidos y frecuencias de variables categóricas en datos estructurados.

data_final |>   
  count(region) |>  
  arrange(desc(n))  
# A tibble: 6 × 2
  region     n
  <chr>  <int>
1 SSA       49
2 AME       32
3 AP        32
4 WE/EU     31
5 ECA       19
6 MENA      18
Nota

En la última línea de código, indicamos a R que ordene los datos de acuerdo a la variable ‘n’, la cual fue definida en la línea de código precedente. Es importante recordar que la ejecución de acciones o funciones en R se realiza de manera secuencial y acumulativa.

2.2.10 Renombrar con rename()

Permite cambiar los nombres de las columnas de un dataframe. Para ello, se especifica el nuevo nombre deseado y el nombre actual de la columna. Esta función es útil cuando se necesita ajustar o estandarizar los nombres de las columnas en un conjunto de datos, facilitando así análisis posteriores y asegurando la claridad y consistencia en la manipulación de los datos.

Primero debes escribir el nuevo nombre y luego el nombre original de la variable.

data_final |>   
  rename(zona=region)   # Renombro la columna "region" (nombre original) como "zona" (nombre nuevo)
# A tibble: 181 × 5
   country      year zona  cpi_score cpi_score2
   <chr>       <dbl> <chr>     <dbl>      <dbl>
 1 Denmark      2022 WE/EU        90         10
 2 Finland      2022 WE/EU        87         13
 3 New Zealand  2022 AP           87         13
 4 Norway       2022 WE/EU        84         16
 5 Singapore    2022 AP           83         17
 6 Sweden       2022 WE/EU        83         17
 7 Switzerland  2022 WE/EU        82         18
 8 Netherlands  2022 WE/EU        80         20
 9 Germany      2022 WE/EU        79         21
10 Ireland      2022 WE/EU        77         23
# ℹ 171 more rows

2.2.11 Recodificar con case_when()

La función case_when() del paquete tidyverse en R sirve para recodificar datos y crear nuevas variables o modificar variables existentes basándose en múltiples condiciones.

Permite evaluar varias condiciones utilizando una sintaxis similar a una instrucción “if-else”. Esta función es particularmente útil cuando necesitamos recodificar una variable en varias categorías o cuando tenemos múltiples condiciones a evaluar.

Se coloca primero la condición (fórmula) seguido del símbolo ~ (alt+126) y la etiqueta.

Al final se coloca TRUE, lo que indica todos aquellos casos que no cumplen con las condiciones anteriores.

summary(data_final$cpi_score2)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  10.00   45.00   60.50   57.02   70.25   88.00       1 
data_final<-data_final |> 
            drop_na(cpi_score2)
            summary(data_final$cpi_score2)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.00   45.00   60.50   57.02   70.25   88.00 

Podemos realizar:

data_final<-data_final  |>   
  mutate(corrupcion=case_when(cpi_score2<30~"Bajo", 
                              cpi_score2<60~"Medio", 
                              cpi_score2<=100~"Alto")) 

Le asignamos la configuración adecuada:

data_final$corrupcion<-factor(data_final$corrupcion,
                          levels = c("Bajo", "Medio", "Alto"),
                          ordered = TRUE)

Finalmente, ya contamos una nueva nueva variable ordinal creada a partir de una variable numérica:

str(data_final$corrupcion)
 Ord.factor w/ 3 levels "Bajo"<"Medio"<..: 1 1 1 1 1 1 1 1 1 1 ...

2.3 Ficha resumen (Cheat Sheet)