05A - Manejo avanzado de datos

Si quieres correr estos scripts localmente, acá puedes descargar el proyecto comprimido en .zip. Paquetes que necesitas tener instalados antes de comenzar con el proyecto (05A, 05B): tidyverse, janitor.

Inicio: cargar paquetes, base de datos

library(tidyverse)
df_tasa_robos <- read_csv("datos/tasa_robos_wide.csv")
## Parsed with column specification:
## cols(
##   comuna = col_character(),
##   comuna_id = col_double(),
##   `2012` = col_double(),
##   `2013` = col_double(),
##   `2014` = col_double(),
##   `2015` = col_double(),
##   `2016` = col_double()
## )

Tenemos una base de datos con los casos policiales de robos cada 1.000 habitantes. Contiene información para 340 comunas de Chile, 2012-2016. Su fuente es la Subsecretaría de Prevención del Delito (2017).

Pivotear bases de datos (wide <-> long)

¿Qué pasa si queremos graficar estos datos, por ejemplo viendo la evolución temporal de la variable en una comuna? El formato de los datos no es el ideal. Aquí los valores de una variable (año) se expandieron hacia las columnas, generando una base en formato wide.

Podemos “alargar” esta base usando la función pivot_longer(), de la siguiente manera:

df_tasa_robos_long <- df_tasa_robos %>% 
  pivot_longer(cols = -c(comuna, comuna_id), # descartamos vars. que no queremos transformar
               names_to = "anio", values_to = "tasa_robos")
df_tasa_robos_long
## # A tibble: 1,700 x 4
##    comuna    comuna_id anio  tasa_robos
##    <chr>         <dbl> <chr>      <dbl>
##  1 Algarrobo      5602 2012       4031.
##  2 Algarrobo      5602 2013       3612.
##  3 Algarrobo      5602 2014       3734.
##  4 Algarrobo      5602 2015       4231.
##  5 Algarrobo      5602 2016       3665.
##  6 Alhué         13502 2012        796.
##  7 Alhué         13502 2013        950.
##  8 Alhué         13502 2014       1167.
##  9 Alhué         13502 2015        606.
## 10 Alhué         13502 2016        956.
## # ... with 1,690 more rows

Esta estructura de datos es mucho más amigable para ggplot2:

ggplot(data = df_tasa_robos_long %>% filter(comuna %in% c("San-Joaquín", "Macul")),
       mapping = aes(x = as.factor(anio), y = tasa_robos, 
                     color = comuna, group = comuna)) +
  geom_line() # podríamos seguir añadiendo escalas, labs, etc...

Noten que pivot_longer() tiene una función recíproca, pivot_wider():

df_tasa_robos_long %>% 
  pivot_wider(names_from = "anio", values_from = "tasa_robos")
## # A tibble: 340 x 7
##    comuna          comuna_id `2012` `2013` `2014` `2015` `2016`
##    <chr>               <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
##  1 Algarrobo            5602  4031.  3612.  3734.  4231.  3665.
##  2 Alhué               13502   796.   950.  1167.   606.   956.
##  3 Alto-Biobío          8314   225.   305.   245.   139.   103.
##  4 Alto-del-Carmen      3302   208.   209.   397.   293.   315.
##  5 Alto-Hospicio        1107  2589.  2218.  1930.  1962.  1847.
##  6 Ancud               10202   579.   763.   697.   755.   732.
##  7 Andacollo            4103   759.   640.   892.   911.  1075.
##  8 Angol                9201  1400.  1515.  1822.  1939.  1468.
##  9 Antártica           12202     0      0      0      0      0 
## 10 Antofagasta          2101  2178.  1892.  1938.  1671.  1391.
## # ... with 330 more rows

Recodificar variables

Supongamos que, usando nuestra nueva base long, queremos crear una variable binaria/dummy que indique si la observación es para el gobierno de Piñera I o Bachelet II. Podemos usar if_else() dentro de mutate():

df_tasa_robos_long %>% 
  mutate(d_gob_bachelet = if_else(condition = anio >= 2014, 
                                  true      = 1,
                                  false     = 0))
## # A tibble: 1,700 x 5
##    comuna    comuna_id anio  tasa_robos d_gob_bachelet
##    <chr>         <dbl> <chr>      <dbl>          <dbl>
##  1 Algarrobo      5602 2012       4031.              0
##  2 Algarrobo      5602 2013       3612.              0
##  3 Algarrobo      5602 2014       3734.              1
##  4 Algarrobo      5602 2015       4231.              1
##  5 Algarrobo      5602 2016       3665.              1
##  6 Alhué         13502 2012        796.              0
##  7 Alhué         13502 2013        950.              0
##  8 Alhué         13502 2014       1167.              1
##  9 Alhué         13502 2015        606.              1
## 10 Alhué         13502 2016        956.              1
## # ... with 1,690 more rows

if_else() nos sirve si es que queremos crear variables binarias (numéricas o no). Pero a menudo queremos asignar más categorías. En esos casos podemos usar case_when():

df_tasa_robos_long %>% 
  mutate(gobierno = case_when(anio < 2014  ~ "Piñera I", # condición ~ valor
                              anio == 2014 ~ "Cambio de mando",
                              anio > 2014  ~ "Bachelet II"))
## # A tibble: 1,700 x 5
##    comuna    comuna_id anio  tasa_robos gobierno       
##    <chr>         <dbl> <chr>      <dbl> <chr>          
##  1 Algarrobo      5602 2012       4031. Piñera I       
##  2 Algarrobo      5602 2013       3612. Piñera I       
##  3 Algarrobo      5602 2014       3734. Cambio de mando
##  4 Algarrobo      5602 2015       4231. Bachelet II    
##  5 Algarrobo      5602 2016       3665. Bachelet II    
##  6 Alhué         13502 2012        796. Piñera I       
##  7 Alhué         13502 2013        950. Piñera I       
##  8 Alhué         13502 2014       1167. Cambio de mando
##  9 Alhué         13502 2015        606. Bachelet II    
## 10 Alhué         13502 2016        956. Bachelet II    
## # ... with 1,690 more rows

Una opción válida al usar case_when() es asignar un valor para “cualquier otro caso”:

df_tasa_robos_long %>% 
  mutate(gobierno = case_when(anio < 2014  ~ "Piñera I", 
                              anio == 2014 ~ "Cambio de mando",
                              TRUE         ~ "Bachelet II")) # en cualquier otro caso
## # A tibble: 1,700 x 5
##    comuna    comuna_id anio  tasa_robos gobierno       
##    <chr>         <dbl> <chr>      <dbl> <chr>          
##  1 Algarrobo      5602 2012       4031. Piñera I       
##  2 Algarrobo      5602 2013       3612. Piñera I       
##  3 Algarrobo      5602 2014       3734. Cambio de mando
##  4 Algarrobo      5602 2015       4231. Bachelet II    
##  5 Algarrobo      5602 2016       3665. Bachelet II    
##  6 Alhué         13502 2012        796. Piñera I       
##  7 Alhué         13502 2013        950. Piñera I       
##  8 Alhué         13502 2014       1167. Cambio de mando
##  9 Alhué         13502 2015        606. Bachelet II    
## 10 Alhué         13502 2016        956. Bachelet II    
## # ... with 1,690 more rows

Mini-ejercicio

Crea la variable d_gob_bachele de antes, pero esta vez usando case_when(). Tu código:

Valores perdidos/missing/NA

Para el resto de la clase trabajaremos también con datos de robos, esta vez para los países del Cono Sur (2006-2016). La fuente es la Oficina de las Naciones Unidas contra la Droga y el Delito (UNODC).

df_robos_cono_sur <- read_csv("datos/robos_cono_sur.csv")
## Parsed with column specification:
## cols(
##   pais = col_character(),
##   pais_codigo = col_character(),
##   anio = col_double(),
##   robos_c100k = col_double()
## )
df_robos_cono_sur
## # A tibble: 33 x 4
##    pais      pais_codigo  anio robos_c100k
##    <chr>     <chr>       <dbl>       <dbl>
##  1 Argentina ARG          2006        738.
##  2 Argentina ARG          2007        662.
##  3 Argentina ARG          2008        704.
##  4 Argentina ARG          2009         NA 
##  5 Argentina ARG          2010         NA 
##  6 Argentina ARG          2011         NA 
##  7 Argentina ARG          2012         NA 
##  8 Argentina ARG          2013         NA 
##  9 Argentina ARG          2014        668.
## 10 Argentina ARG          2015        626.
## # ... with 23 more rows

Veamos los datos. ¿Qué pasó con las datos de Argentina, 2009-2013?

R registra los valores perdidos como “NA”. Esto no es un caracter con las letras N y A, sino que un valor especial dentro del vector, sin importar su tipo.

Realizar operaciones básicas en vectores con NA

Intentemos calcular la media por país para la variable “robos_c100k”:

df_robos_cono_sur %>% 
  group_by(pais) %>% 
  summarize(media_robos_c100k = mean(robos_c100k))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 3 x 2
##   pais      media_robos_c100k
##   <chr>                 <dbl>
## 1 Argentina               NA 
## 2 Chile                 1070.
## 3 Uruguay               2984.

La mayoría de las operaciones básicas en R (median(), sd(), sum(), etc.) fallarán cuando alguno de los valores en el cálculo sea un NA. Si es que de todas formas queremos utilizar la función, tomando en cuenta solo los valores existentes, prácticamente todas estas operaciones incluyen un argumento na.rm = (NA remove):

df_robos_cono_sur %>% 
  group_by(pais) %>% 
  summarize(media_robos_c100k = mean(robos_c100k, na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 3 x 2
##   pais      media_robos_c100k
##   <chr>                 <dbl>
## 1 Argentina              669.
## 2 Chile                 1070.
## 3 Uruguay               2984.

Por defecto, los modelos de regresión hacen algo como esto, omiten las observaciones que tengan NA en alguna de las variables del modelo. Siempre que estemos en la duda sobre cómo se comporta alguna función ante NAs, deberíamos revisar su archivo de ayuda y buscar algún argumento que incluya “na”:

?lm

Filtrar NAs de una base

Lo siguiente no funcionará:

df_robos_cono_sur %>% 
  filter(robos_c100k == NA)

Lo que debemos utilizar en operaciones lógicas para testear la presencia de NAs es la función is.na():

df_robos_cono_sur %>% 
  filter(is.na(robos_c100k))
## # A tibble: 5 x 4
##   pais      pais_codigo  anio robos_c100k
##   <chr>     <chr>       <dbl>       <dbl>
## 1 Argentina ARG          2009          NA
## 2 Argentina ARG          2010          NA
## 3 Argentina ARG          2011          NA
## 4 Argentina ARG          2012          NA
## 5 Argentina ARG          2013          NA

Podemos realizar una negación en una operación lógica antecediéndola de un signo de exclamación. En este caso, obtendremos solo las observaciones que no tienen NA en “robos_c100k”:

df_robos_cono_sur %>% 
  filter(!is.na(robos_c100k))
## # A tibble: 28 x 4
##    pais      pais_codigo  anio robos_c100k
##    <chr>     <chr>       <dbl>       <dbl>
##  1 Argentina ARG          2006        738.
##  2 Argentina ARG          2007        662.
##  3 Argentina ARG          2008        704.
##  4 Argentina ARG          2014        668.
##  5 Argentina ARG          2015        626.
##  6 Argentina ARG          2016        616.
##  7 Chile     CHL          2006        942.
##  8 Chile     CHL          2007       1018.
##  9 Chile     CHL          2008       1054.
## 10 Chile     CHL          2009       1136.
## # ... with 18 more rows

Crear valores perdidos

df_robos_cono_sur
## # A tibble: 33 x 4
##    pais      pais_codigo  anio robos_c100k
##    <chr>     <chr>       <dbl>       <dbl>
##  1 Argentina ARG          2006        738.
##  2 Argentina ARG          2007        662.
##  3 Argentina ARG          2008        704.
##  4 Argentina ARG          2009         NA 
##  5 Argentina ARG          2010         NA 
##  6 Argentina ARG          2011         NA 
##  7 Argentina ARG          2012         NA 
##  8 Argentina ARG          2013         NA 
##  9 Argentina ARG          2014        668.
## 10 Argentina ARG          2015        626.
## # ... with 23 more rows

Supongamos que no confiamos en los datos más antiguos para Argentina (2006-2008) y también queremos asignarlos como valores perdidos. Una opción podría ser eliminar dichas observaciones con filter(), pero tal vez tenemos información útil en otras variables.

Podríamos asignarle el valor de NA a dichas observaciones con if_else() o case_when():

df_robos_cono_sur %>% 
  mutate(robos_c100k = case_when(
    pais == "Argentina" & anio <= 2008 ~ NA,
    TRUE                               ~ robos_c100k
  ))

Lo anterior falla, pese a que la sintaxis de case_when() es correcta! El problema es que cuando creamos valores perdidos debemos decirle explícitamente a R qué tipo de NAs utilizaremos, según el tipo de vector. Los tipos más comunes son NA_character_ (para vectores de caracteres, chr) o NA_real_ (para vectores de números reales, dbl). Veamos cómo ahora funcionará:

df_robos_cono_sur %>% 
  mutate(robos_c100k = case_when(
    pais == "Argentina" & anio <= 2008 ~ NA_real_,
    TRUE                               ~ robos_c100k
  ))
## # A tibble: 33 x 4
##    pais      pais_codigo  anio robos_c100k
##    <chr>     <chr>       <dbl>       <dbl>
##  1 Argentina ARG          2006         NA 
##  2 Argentina ARG          2007         NA 
##  3 Argentina ARG          2008         NA 
##  4 Argentina ARG          2009         NA 
##  5 Argentina ARG          2010         NA 
##  6 Argentina ARG          2011         NA 
##  7 Argentina ARG          2012         NA 
##  8 Argentina ARG          2013         NA 
##  9 Argentina ARG          2014        668.
## 10 Argentina ARG          2015        626.
## # ... with 23 more rows

Unir bases de datos

Aquí tenemos una base con muchos datos de los World Development Indicators del Banco Mundial. Están para los tres países del Cono Sur, pero desde 2007 a 2016 (falta 2006, en comparación a los datos anteriores).

df_wdi <- read_csv("datos/wdi_cono_sur.csv")
## Parsed with column specification:
## cols(
##   .default = col_double(),
##   pais_codigo = col_character(),
##   external_debt_stocks_total_dod_current_us = col_logical(),
##   total_debt_service_percent_of_exports_of_goods_services_and_primary_income = col_logical()
## )
## See spec(...) for full column specifications.
df_wdi
## # A tibble: 30 x 57
##    pais_codigo  anio population_total population_grow~ surface_area_sq~ population_dens~ poverty_headcou~ poverty_headcou~ gni_atlas_metho~ gni_per_capita_~ gni_ppp_current~ gni_per_capita_~ income_share_he~ life_expectancy~ fertility_rate_~
##    <chr>       <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>
##  1 ARG          2007         39684295            0.999         2780400              14.5             NA                2.9    258429317135.             6510    656745628034.            16550              3.9             74.8             2.38
##  2 CHL          2007         16530195            1.07           756096.             22.2             NA               NA      143603828921.             8690    248814945028.            15050             NA               78.1             1.90
##  3 URY          2007          3331749            0.191          176220              19.0             29.6              0.3     21283077870.             6390     44113794683.            13240              4.8             76.3             2.05
##  4 ARG          2008         40080160            0.993         2780400              14.6             NA                2.6    307363845739.             7670    697740913973.            17410              4               75.0             2.37
##  5 CHL          2008         16708258            1.07           756096.             22.5             NA               NA      167969056839.            10050    254260262605.            15220             NA               78.3             1.90
##  6 URY          2008          3340221            0.254          176220              19.1             24.2              0.2     25752230257.             7710     47817999408.            14320              5               76.4             2.03
##  7 ARG          2009         40482788            1.00          2780400              14.8             NA                2.6    315586430026.             7800    657382734891.            16240              4               75.1             2.36
##  8 CHL          2009         16886186            1.06           756096.             22.7             25.3              2.6    168009833889.             9950    254255791261.            15060              4.6             78.6             1.89
##  9 URY          2009          3349676            0.283          176220              19.1             21                0.2     29494248573.             8810     50075569089.            14950              4.8             76.6             2.02
## 10 ARG          2010         40788453            0.752         2780400              14.9             NA                1.1    378241273936.             9270    729853440301.            17890              4.6             75.3             2.35
## # ... with 20 more rows, and 42 more variables: adolescent_fertility_rate_births_per_1_000_women_ages_15_19 <dbl>, contraceptive_prevalence_any_methods_percent_of_women_ages_15_49 <dbl>,
## #   births_attended_by_skilled_health_staff_percent_of_total <dbl>, mortality_rate_under_5_per_1_000_live_births <dbl>, prevalence_of_underweight_weight_for_age_percent_of_children_under_5 <dbl>,
## #   immunization_measles_percent_of_children_ages_12_23_months <dbl>, primary_completion_rate_total_percent_of_relevant_age_group <dbl>, school_enrollment_primary_percent_gross <dbl>, school_enrollment_secondary_percent_gross <dbl>,
## #   school_enrollment_primary_and_secondary_gross_gender_parity_index_gpi <dbl>, prevalence_of_hiv_total_percent_of_population_ages_15_49 <dbl>, forest_area_sq_km <dbl>, terrestrial_and_marine_protected_areas_percent_of_total_territorial_area <dbl>,
## #   annual_freshwater_withdrawals_total_percent_of_internal_resources <dbl>, urban_population_growth_annual_percent <dbl>, energy_use_kg_of_oil_equivalent_per_capita <dbl>, co2_emissions_metric_tons_per_capita <dbl>,
## #   electric_power_consumption_k_wh_per_capita <dbl>, gdp_current_us <dbl>, gdp_growth_annual_percent <dbl>, inflation_gdp_deflator_annual_percent <dbl>, agriculture_forestry_and_fishing_value_added_percent_of_gdp <dbl>,
## #   industry_including_construction_value_added_percent_of_gdp <dbl>, exports_of_goods_and_services_percent_of_gdp <dbl>, imports_of_goods_and_services_percent_of_gdp <dbl>, gross_capital_formation_percent_of_gdp <dbl>,
## #   revenue_excluding_grants_percent_of_gdp <dbl>, time_required_to_start_a_business_days <dbl>, domestic_credit_provided_by_financial_sector_percent_of_gdp <dbl>, tax_revenue_percent_of_gdp <dbl>, military_expenditure_percent_of_gdp <dbl>,
## #   mobile_cellular_subscriptions_per_100_people <dbl>, high_technology_exports_percent_of_manufactured_exports <dbl>, statistical_capacity_score_overall_average <dbl>, merchandise_trade_percent_of_gdp <dbl>,
## #   net_barter_terms_of_trade_index_2000_100 <dbl>, external_debt_stocks_total_dod_current_us <lgl>, total_debt_service_percent_of_exports_of_goods_services_and_primary_income <lgl>, net_migration <dbl>,
## #   personal_remittances_received_current_us <dbl>, foreign_direct_investment_net_inflows_bo_p_current_us <dbl>, net_official_development_assistance_and_official_aid_received_current_us <dbl>

¿Cómo podemos añadir toda esta nueva información a nuestra base original? No podemos simplemente pegar las columnas unas al lado de otras con bind_cols() (los números de filas son distintos, lo mismo con el orden de las observaciones).

Lo mejor es realizar una unión de bases (merge/join). Lejos la más común de estas operaciones es la unión izquierda, en la que queremos añadir información a una base (la izquierda) a partir de otra (la derecha). left_join() nos permitirá hacer esto, mirando las observaciones de ambas bases donde las columnas de identificación toman los mismos valores:

df_robos_cono_sur_con_wdi <- left_join(
  x = df_robos_cono_sur, y = df_wdi,
  by = c("pais_codigo", "anio") # by dice cuáles son las variables de id.
)
df_robos_cono_sur_con_wdi
## # A tibble: 33 x 59
##    pais  pais_codigo  anio robos_c100k population_total population_grow~ surface_area_sq~ population_dens~ poverty_headcou~ poverty_headcou~ gni_atlas_metho~ gni_per_capita_~ gni_ppp_current~ gni_per_capita_~ income_share_he~ life_expectancy~
##    <chr> <chr>       <dbl>       <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>            <dbl>
##  1 Arge~ ARG          2006        738.               NA           NA                   NA             NA                 NA             NA                NA                NA              NA                NA             NA               NA  
##  2 Arge~ ARG          2007        662.         39684295            0.999          2780400             14.5               NA              2.9    258429317135.             6510    656745628034.            16550              3.9             74.8
##  3 Arge~ ARG          2008        704.         40080160            0.993          2780400             14.6               NA              2.6    307363845739.             7670    697740913973.            17410              4               75.0
##  4 Arge~ ARG          2009         NA          40482788            1.00           2780400             14.8               NA              2.6    315586430026.             7800    657382734891.            16240              4               75.1
##  5 Arge~ ARG          2010         NA          40788453            0.752          2780400             14.9               NA              1.1    378241273936.             9270    729853440301.            17890              4.6             75.3
##  6 Arge~ ARG          2011         NA          41261490            1.15           2780400             15.1               NA              0.9    442037545216.            10710    794325172722.            19250              4.8             75.4
##  7 Arge~ ARG          2012         NA          41733271            1.14           2780400             15.2               NA              0.8    496046283910.            11890    805324243205.            19300              4.9             75.6
##  8 Arge~ ARG          2013         NA          42202935            1.12           2780400             15.4               NA              0.8    543285805981.            12870    841055034261.            19930              5               75.8
##  9 Arge~ ARG          2014        668.         42669500            1.10           2780400             15.6               NA              0.7    526784533342.            12350    836246704582.            19600              5.1             75.9
## 10 Arge~ ARG          2015        626.         43131966            1.08           2780400             15.8               NA             NA      543279945585.            12600    869846606665.            20170             NA               76.1
## # ... with 23 more rows, and 43 more variables: fertility_rate_total_births_per_woman <dbl>, adolescent_fertility_rate_births_per_1_000_women_ages_15_19 <dbl>, contraceptive_prevalence_any_methods_percent_of_women_ages_15_49 <dbl>,
## #   births_attended_by_skilled_health_staff_percent_of_total <dbl>, mortality_rate_under_5_per_1_000_live_births <dbl>, prevalence_of_underweight_weight_for_age_percent_of_children_under_5 <dbl>,
## #   immunization_measles_percent_of_children_ages_12_23_months <dbl>, primary_completion_rate_total_percent_of_relevant_age_group <dbl>, school_enrollment_primary_percent_gross <dbl>, school_enrollment_secondary_percent_gross <dbl>,
## #   school_enrollment_primary_and_secondary_gross_gender_parity_index_gpi <dbl>, prevalence_of_hiv_total_percent_of_population_ages_15_49 <dbl>, forest_area_sq_km <dbl>, terrestrial_and_marine_protected_areas_percent_of_total_territorial_area <dbl>,
## #   annual_freshwater_withdrawals_total_percent_of_internal_resources <dbl>, urban_population_growth_annual_percent <dbl>, energy_use_kg_of_oil_equivalent_per_capita <dbl>, co2_emissions_metric_tons_per_capita <dbl>,
## #   electric_power_consumption_k_wh_per_capita <dbl>, gdp_current_us <dbl>, gdp_growth_annual_percent <dbl>, inflation_gdp_deflator_annual_percent <dbl>, agriculture_forestry_and_fishing_value_added_percent_of_gdp <dbl>,
## #   industry_including_construction_value_added_percent_of_gdp <dbl>, exports_of_goods_and_services_percent_of_gdp <dbl>, imports_of_goods_and_services_percent_of_gdp <dbl>, gross_capital_formation_percent_of_gdp <dbl>,
## #   revenue_excluding_grants_percent_of_gdp <dbl>, time_required_to_start_a_business_days <dbl>, domestic_credit_provided_by_financial_sector_percent_of_gdp <dbl>, tax_revenue_percent_of_gdp <dbl>, military_expenditure_percent_of_gdp <dbl>,
## #   mobile_cellular_subscriptions_per_100_people <dbl>, high_technology_exports_percent_of_manufactured_exports <dbl>, statistical_capacity_score_overall_average <dbl>, merchandise_trade_percent_of_gdp <dbl>,
## #   net_barter_terms_of_trade_index_2000_100 <dbl>, external_debt_stocks_total_dod_current_us <lgl>, total_debt_service_percent_of_exports_of_goods_services_and_primary_income <lgl>, net_migration <dbl>,
## #   personal_remittances_received_current_us <dbl>, foreign_direct_investment_net_inflows_bo_p_current_us <dbl>, net_official_development_assistance_and_official_aid_received_current_us <dbl>