Análisis Exploratorio de Datos para Machine Learning I

Primeros pasos con tidyverse: importación, estructura y manipulación básica

Christian Chiroque

Etapas de un proyecto de ML

Recuerda las etapas que hemos establecido:

Igual que un chef no cocina con ingredientes sucios o sin cortar, en ML no se puede usar la data en bruto.

Entendiendo el negocio

Contexto

Eres parte del equipo de investigación del Grupo de Acción Financiera Internacional que brinda información para la lucha contra diversos crímenes financieros, entre estos el lavado de activos.

Pregunta

Se desea desarrollar un modelo predictivo que pueda predecir el riesgo de LAFT en un país a partir de distintas variables sociales, políticas o económicas.

Esto será de gran ayuda para los procesos de seguimiento y evaluación que el GAFI realiza a nivel mundial.

Instalamos y abrimos la librería

# install.packages("tidyverse")
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.2     ✔ tibble    3.3.0
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.1.0     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Importación de dataset

Podemos abrir nuestra base de datos utilizando:

library(readxl)
data<-read_xlsx("AML_1.xlsx")
data
# A tibble: 95 × 18
   `Año de medicion` var_151_2 var_151_3 var_151_4 region antimoneylaundering …¹
               <dbl>     <dbl> <chr>     <chr>     <chr>  <chr>                 
 1              2022         1 Afghanis… Asia      South… No se detectó informa…
 2              2022         2 Albania   Europe    Centr… 4.75                  
 3              2022         3 Angola    Africa    Centr… 7.03                  
 4              2022         4 Argentina Americas  South… No se detectó informa…
 5              2022         5 Armenia   Asia      Centr… 4.72                  
 6              2022         6 Austria   Europe    Weste… 4.1                   
 7              2022         7 Banglade… Asia      South… 5.8                   
 8              2022         8 Belarus   Europe    Centr… 5.33                  
 9              2022         9 Belgium   Europe    Weste… 4.13                  
10              2022        10 Belize    Americas  Carib… No se detectó informa…
# ℹ 85 more rows
# ℹ abbreviated name: ¹​`antimoneylaundering Index of Basel Institute`
# ℹ 12 more variables: Matricula <dbl>, `PBI PC` <dbl>, Pobreza <dbl>,
#   `porcentaje URBANO` <dbl>, `Gasto en educacion` <dbl>, CPI_Index <dbl>,
#   Rule_of_Law <dbl>, Democracy_Index <dbl>, Democracy_Index_cat <chr>,
#   Organized_Crime_Index <dbl>, Organized_Crime_Index_cat <chr>,
#   `Freedom in the World` <dbl>

Entendiendo mi data

Realidad

  • Las fases de comprensión y preparación de los datos suelen ocupar la mayor parte del esfuerzo de un proyecto (se suele hablar de entre 60% y 80%).

  • No obstante es la parte con menos hype.

Objetivo

Los pasos mínimos que aprenderemos será:

  • Importación de datos
  • Identificar dimensión de dataset
  • Identificar el tipo de atributos (variables)
  • Resumir
  • Visualizar
  • Identificar problemas potenciales

Bienvenidos al Tidyverse

El tidyverse es un conjunto de paquetes de R diseñados para trabajar de forma coherente con datos:

  • Datos ordenados (tidy data): cada columna es una variable, cada fila es una observación y cada celda un valor.
  • Gramática consistente: las funciones siguen una lógica similar y se combinan con el operador |> o %>% (pipe) para crear flujos de trabajo legibles.

Warning

Para entender Tidymodels primero debemos aprender Tidyverse.

Paquetes del tidyverse

Exploración inicial

¿Qué podemos identificar?

glimpse(data)
Rows: 95
Columns: 18
$ `Año de medicion`                              <dbl> 2022, 2022, 2022, 2022,…
$ var_151_2                                      <dbl> 1, 2, 3, 4, 5, 6, 7, 8,…
$ var_151_3                                      <chr> "Afghanistan", "Albania…
$ var_151_4                                      <chr> "Asia", "Europe", "Afri…
$ region                                         <chr> "Southern Asia", "Centr…
$ `antimoneylaundering Index of Basel Institute` <chr> "No se detectó informac…
$ Matricula                                      <dbl> 50.14, 86.61, 11.29, 90…
$ `PBI PC`                                       <dbl> 551.87, 5223.81, 3437.3…
$ Pobreza                                        <dbl> 54.5, 14.3, 36.6, 25.7,…
$ `porcentaje URBANO`                            <dbl> 26.0, 62.1, 66.8, 92.1,…
$ `Gasto en educacion`                           <dbl> 4.06, 2.47, 3.42, 5.46,…
$ CPI_Index                                      <dbl> 24, 36, 33, 38, 46, 71,…
$ Rule_of_Law                                    <dbl> 0.3175542, 0.4840872, 0…
$ Democracy_Index                                <dbl> 0.32, 6.41, 3.96, 6.85,…
$ Democracy_Index_cat                            <chr> "Authoritarian", "Flawe…
$ Organized_Crime_Index                          <dbl> 7.10, 5.17, 5.58, 5.00,…
$ Organized_Crime_Index_cat                      <chr> "Alto", "Medio", "Medio…
$ `Freedom in the World`                         <dbl> NA, NA, NA, NA, NA, NA,…

Identificación teórica de las variables

Configuración inicial: numéricas

Detectamos una variable que debería ser numérica pero tiene otra configuración.

str(data$`antimoneylaundering Index of Basel Institute`)
 chr [1:95] "No se detectó información" "4.75" "7.03" ...

Podemos forzar a que sea leída como numérica:

as.numeric(data$`antimoneylaundering Index of Basel Institute`)
 [1]   NA 4.75 7.03   NA 4.72 4.10 5.80 5.33 4.13   NA 6.62 5.89   NA 5.16 6.48
[16]   NA 6.75   NA 8.14 4.13 4.74   NA 4.72 4.66 3.36   NA 5.21 5.06   NA   NA
[31] 3.00 5.54 4.70 3.58 4.69 4.29 5.29 3.70 5.38 7.69   NA 5.60 4.94   NA 4.56
[46] 5.29 4.90 4.71 4.00   NA 7.17 3.47 7.43 5.63 5.21 7.06 4.65 6.62 4.74 5.21
[61] 7.88   NA 4.15 6.42 6.64 5.44 5.76   NA 5.07 4.81 5.64 4.46 4.08 4.90   NA
[76] 6.67 4.74 5.23 7.09 3.57 5.85 3.96 5.42 3.20 4.05 5.91 5.82 6.95 6.43 5.53
[91] 5.08 4.30 4.08 5.12 5.52

Cuidado

Important

Debes crear un nuevo objeto o sobrescribir uno existente usando el símbolo de asignación; de lo contrario, el programa solo mostrará los cambios, pero no los aplicará realmente.

data$`antimoneylaundering Index of Basel Institute` <- as.numeric(data$`antimoneylaundering Index of Basel Institute`)

Important

En R, NA significa Not Available y se usa para representar un valor faltante o desconocido en los datos.

Configuración inicial: factores

  • Tipo especial de objeto para datos categóricos.

  • Guardan la categoría como etiqueta (nivel).

  • Permiten que R distinga entre categóricas nominales (ej. color: rojo, azul, verde) o categóricas ordinales (ej. nivel: bajo < medio < alto).

Important

Los factores ayudan a ordenar y entender categorías antes de transformarlas en números para un modelo. Si no lo haces, puedes errar tanto en la parte descriptiva como la de modelamiento.

Configuración inicial: factores no ordenados

Veamos la variable var_151_4:

str(data$var_151_4)
 chr [1:95] "Asia" "Europe" "Africa" "Americas" "Asia" "Europe" "Asia" ...

Lo convertimos en factor no ordenado:

data$var_151_4 <- factor(data$var_151_4)

Confirmamos:

str(data$var_151_4)
 Factor w/ 5 levels "Africa","Americas",..: 3 4 1 2 3 4 3 4 4 2 ...

Configuración inicial: factores ordenados

Veamos la variable Organized_Crime_Index_cat:

str(data$Organized_Crime_Index_cat)
 chr [1:95] "Alto" "Medio" "Medio" "Medio" "Bajo" "Medio" "Medio" "Medio" ...

Lo convertimos en factor ordenado:

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

Confirmamos:

str(data$Organized_Crime_Index_cat)
 Ord.factor w/ 3 levels "Bajo"<"Medio"<..: 3 2 2 2 1 2 2 2 2 2 ...

Estadísticos descriptivos

Para comenzar con la exploración podemos utilizar la función ´summary()´. Por ejemplo, con una variable numérica:

summary(data$`antimoneylaundering Index of Basel Institute`)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  3.000   4.605   5.160   5.261   5.835   8.140      16 

O una variable factor:

summary(data$Organized_Crime_Index_cat)
 Bajo Medio  Alto 
    2    81    12 

Criterios para seleccionar variables

  • Mantener solo variables relevantes para el objetivo.

  • Descartar variables con varianza cero (no cambia).

  • Elegir variables con pocos valores faltantes o, si los hay, aplicar imputación (después volveremos a esto).

Tu turno: selecciona tus variables

A la luz de los criterios expuesto, ¿qué variables no vamos a utilizar?

Seleccionamos variables con select()

Puedo escribir el nombre o número de la variable o variables que quiero seleccionar:

data |> select(1)
# A tibble: 95 × 1
   `Año de medicion`
               <dbl>
 1              2022
 2              2022
 3              2022
 4              2022
 5              2022
 6              2022
 7              2022
 8              2022
 9              2022
10              2022
# ℹ 85 more rows

Seleccionamos variables con select()

Puedo escribir el nombre o número de la variable o variables que NO quiero seleccionar:

data |> select(-1)
# A tibble: 95 × 17
   var_151_2 var_151_3   var_151_4 region       antimoneylaundering …¹ Matricula
       <dbl> <chr>       <fct>     <chr>                         <dbl>     <dbl>
 1         1 Afghanistan Asia      Southern As…                  NA         50.1
 2         2 Albania     Europe    Central & E…                   4.75      86.6
 3         3 Angola      Africa    Central Afr…                   7.03      11.3
 4         4 Argentina   Americas  South Ameri…                  NA         90.8
 5         5 Armenia     Asia      Central Asi…                   4.72      87.7
 6         6 Austria     Europe    Western Eur…                   4.1       87  
 7         7 Bangladesh  Asia      Southern As…                   5.8       66.6
 8         8 Belarus     Europe    Central & E…                   5.33      95.6
 9         9 Belgium     Europe    Western Eur…                   4.13      95.0
10        10 Belize      Americas  Caribbean &…                  NA         71.2
# ℹ 85 more rows
# ℹ abbreviated name: ¹​`antimoneylaundering Index of Basel Institute`
# ℹ 11 more variables: `PBI PC` <dbl>, Pobreza <dbl>,
#   `porcentaje URBANO` <dbl>, `Gasto en educacion` <dbl>, CPI_Index <dbl>,
#   Rule_of_Law <dbl>, Democracy_Index <dbl>, Democracy_Index_cat <chr>,
#   Organized_Crime_Index <dbl>, Organized_Crime_Index_cat <ord>,
#   `Freedom in the World` <dbl>

Entonces…

data <- data |> 
          select(-`Año de medicion`,     # Cero varianza
                 -var_151_2,              # Número de orden, no es importante.
                 -`Freedom in the World`) # Muchos perdidos
# Recuerda que si el nombre tiene espacios tendrás que escribirlo entre ``. ALT + 96

Y nos quedamos con:

 [1] "var_151_3"                                   
 [2] "var_151_4"                                   
 [3] "region"                                      
 [4] "antimoneylaundering Index of Basel Institute"
 [5] "Matricula"                                   
 [6] "PBI PC"                                      
 [7] "Pobreza"                                     
 [8] "porcentaje URBANO"                           
 [9] "Gasto en educacion"                          
[10] "CPI_Index"                                   
[11] "Rule_of_Law"                                 
[12] "Democracy_Index"                             
[13] "Democracy_Index_cat"                         
[14] "Organized_Crime_Index"                       
[15] "Organized_Crime_Index_cat"                   

Criterios para nombrar variables

  • Mantenlo simple: mi_variable.

  • Ser descriptivo y claro: mejor edad_promedio que ep o x1.

  • Evitar tildes, espacios, mayúsculas al inicio o caracteres especiales.

  • Consistencia: Mantener el mismo estilo.

  • Evitar nombres demasiado largos.

Tu turno: renombra tus variables

Analiza nuevamente las variables e identifica cuáles deberías editar.

names(data)
 [1] "var_151_3"                                   
 [2] "var_151_4"                                   
 [3] "region"                                      
 [4] "antimoneylaundering Index of Basel Institute"
 [5] "Matricula"                                   
 [6] "PBI PC"                                      
 [7] "Pobreza"                                     
 [8] "porcentaje URBANO"                           
 [9] "Gasto en educacion"                          
[10] "CPI_Index"                                   
[11] "Rule_of_Law"                                 
[12] "Democracy_Index"                             
[13] "Democracy_Index_cat"                         
[14] "Organized_Crime_Index"                       
[15] "Organized_Crime_Index_cat"                   

Cambiamos el nombre con rename()

Podemos utilizar la función rename().

Puedes escribir el pipe utilizando Ctrl + Shift + M.

data <- data |> rename(pais=var_151_3)
names(data)
 [1] "pais"                                        
 [2] "var_151_4"                                   
 [3] "region"                                      
 [4] "antimoneylaundering Index of Basel Institute"
 [5] "Matricula"                                   
 [6] "PBI PC"                                      
 [7] "Pobreza"                                     
 [8] "porcentaje URBANO"                           
 [9] "Gasto en educacion"                          
[10] "CPI_Index"                                   
[11] "Rule_of_Law"                                 
[12] "Democracy_Index"                             
[13] "Democracy_Index_cat"                         
[14] "Organized_Crime_Index"                       
[15] "Organized_Crime_Index_cat"                   

Cambiamos el nombre con rename()

data <- data |> rename(continente=var_151_4, 
                       aml_index=`antimoneylaundering Index of Basel Institute`,
                       matricula= Matricula,
                       pbi_pc=`PBI PC`,
                       pobreza=Pobreza,
                       urbano=`porcentaje URBANO`,
                       educacion=`Gasto en educacion`,
                       cpi_index= CPI_Index,
                       rule_of_law=Rule_of_Law,
                       democracy_index=Democracy_Index,
                       democracy_index_cat=Democracy_Index_cat,
                       organized_crime_index= Organized_Crime_Index,
                       organized_crime_index_cat=Organized_Crime_Index_cat)
names(data)
 [1] "pais"                      "continente"               
 [3] "region"                    "aml_index"                
 [5] "matricula"                 "pbi_pc"                   
 [7] "pobreza"                   "urbano"                   
 [9] "educacion"                 "cpi_index"                
[11] "rule_of_law"               "democracy_index"          
[13] "democracy_index_cat"       "organized_crime_index"    
[15] "organized_crime_index_cat"

Lista final de variables

Variables numéricas (10):

  1. aml_index

  2. matricula

  3. pbi_pc

  4. pobreza

  5. urbano

  6. educacion

  7. cpi_index

  8. rule_of_law

  1. democracy_index

  2. organized_crime_index

Factores (4):

  1. continente

  2. region

  3. democracy_index_cat

  4. organized_crime_index_cat