Taller 6: Time-Series

Carlos Daboin Contreras (cdaboincontreras@udesa.edu.ar)

2023-11-01

Resumen de contenido

Nuestra meta

  • Nos familiarizremos con las estructuras de datos time-series.

  • Repasaremos como visualizarlos.

  • Aprenderemos a capturar tendencias temporales con la regresion lineal.

  • Armaremos contrafactuales con tendencias (proyecciones).

  • Usaremos las tendencias para hacer pronósticos de cara al futuro.

Conceptos

  • Time-series.

  • Proyecciones.

  • Rezagos temporales.

Herramientas

  • lm()

  • ggplot2

  • broom:tidy

  • broom:agument_cols

Librerías

Usaremos las siguientes librerías:

library(tidyverse)   # libreria muy usada para manipular los datos y hacer grficos
library(modelsummary)# para tablas
library(broom)       # Revisar modelos
library(wbstats)     # Datos actualizados del WB. Instalar: install.packages("wbstats")
library(janitor)     # Limpiar nombres de columnas

Time-series

Repasaremos tips útiles para presentar análizar series de tiempo.

Mortalidad infantil en Argentina

Accederemos a los datos de mortalidad infantil que discutimos en clase, esta vez de una manera mas éxpedita.

¿Qué es wbstats?

Es una librería que facilita la interacción con la API del BM. Pueden leer mas en este link.

library(wbstats)

# Ingles es default, pero puedo pedir español
new_cache <- wb_cache(lang = "es")

# Variables relacionadas a mortalidad
ev_vars<- wb_search(pattern = "tasa de mortalidad",cache = new_cache)

tail(ev_vars, 20)

Mortalidad infantil en Argentina

# A tibble: 20 × 3
   indicator_id      indicator                                    indicator_desc
   <chr>             <chr>                                        <chr>         
 1 HD.HCI.AMRT.FE    "Años de escolaridad previstos, femenino \r… "El indicador…
 2 HD.HCI.AMRT.MA    "Años de escolaridad previstos, masculino\r… "El indicador…
 3 HD.HCI.MORT       "Probabilidad de supervivencia hasta los 5 … "El indicador…
 4 HD.HCI.MORT.FE    "Probabilidad de supervivencia hasta los 5 … "El indicador…
 5 HD.HCI.MORT.MA    "Probabilidad de supervivencia hasta los 5 … "El indicador…
 6 SH.DYN.CHLD.FE    "Tasa de mortalidad, niñas (por cada 1.000 … "La tasa de m…
 7 SH.DYN.CHLD.MA    "Tasa de mortalidad, niños (por cada 1.000 … "La tasa de m…
 8 SH.DYN.MORT       "Tasa de mortalidad, menores de 5 años (por… "Menores de c…
 9 SH.DYN.MORT.FE    "Tasa de mortalidad, menores de 5 años, muj… "Menores de c…
10 SH.DYN.MORT.MA    "Tasa de mortalidad, menores de 5 años, var… "Menores de c…
11 SH.DYN.NMRT       "Tasa de mortalidad, neonatal (por cada 1.0… "La tasa de m…
12 SH.STA.MMRT       "Tasa de mortalidad materna (estimado media… "La tasa de m…
13 SH.STA.MMRT.NE    "Tasa de mortalidad maternal (cifras nacion… "La tasa de m…
14 SH.STA.SUIC.P5    "Tasa de mortalidad por suicidio (por cada … "Suicide mort…
15 SP.DYN.AMRT.FE    "Tasa de mortalidad, adultos, mujeres (por … "La tasa de m…
16 SP.DYN.AMRT.MA    "Tasa de mortalidad, adultos, varones (por … "La tasa de m…
17 SP.DYN.CDRT.IN    "Tasa de mortalidad en un año (por cada 1.0… "La tasa brut…
18 SP.DYN.IMRT.FE.IN "Tasa de mortalidad infantil, mujeres (cada… "La tasa de m…
19 SP.DYN.IMRT.IN    "Tasa de mortalidad, bebés (por cada 1.000 … "La tasa de m…
20 SP.DYN.IMRT.MA.IN "Tasa de mortalidad infantil, varones (cada… "La tasa de m…

Acceder a los datos

Ya conozco el código de mi indicador (Prob. de Supervivencia hasta los 5 años).

Ahora solo debo especificar la geografía y período de interés.

# Puedes añadir varios paises, con minusculas, mayusculas, o abreviaciones
# Es valido ARG, Arg, Argentina, ArGenTina, etc
# Identifica todos los iso3c, iso2c, country, region_iso3c, admin_region_iso3c, admin_region, income_level

example_geos <- c("Argentina")
ev_data <- wb_data("SH.DYN.MORT", country = example_geos,
                    start_date = 1990, end_date = 2021) 
head(ev_data)
# A tibble: 6 × 9
  iso2c iso3c country    date SH.DYN.MORT unit  obs_status footnote last_updated
  <chr> <chr> <chr>     <dbl>       <dbl> <chr> <chr>      <chr>    <date>      
1 AR    ARG   Argentina  1990        28.8 <NA>  <NA>       Uncerta… 2023-10-26  
2 AR    ARG   Argentina  1991        28.3 <NA>  <NA>       Uncerta… 2023-10-26  
3 AR    ARG   Argentina  1992        27.6 <NA>  <NA>       Uncerta… 2023-10-26  
4 AR    ARG   Argentina  1993        26.5 <NA>  <NA>       Uncerta… 2023-10-26  
5 AR    ARG   Argentina  1994        25.4 <NA>  <NA>       Uncerta… 2023-10-26  
6 AR    ARG   Argentina  1995        24.3 <NA>  <NA>       Uncerta… 2023-10-26  

Cambio en la mortalidad infantil entre 2019 y 2021

Limpieza general:

ev_data<-ev_data %>%
  # remuevo puntos y mayusc de los nombres
  janitor::clean_names() %>% 
  # cambio el nombre a algo facil de recordar
  rename(mortalidad_infantil=sh_dyn_mort)

ev_data_19_21<-ev_data %>% 
  # me quedo con los registros de dos anos
  filter(date %in% c(2019,2021))

Calculo before-after:

ev_data_19_21 %>% 
  # solo me interesan fecha y mortalidad inf.
  select(date,mortalidad_infantil) %>% 
  # transpongo los datos para restarlos y presentarlos
  pivot_wider(names_from = "date", 
              values_from = "mortalidad_infantil") %>% 
  mutate(diff= `2021`-`2019`)
# A tibble: 1 × 3
  `2019` `2021`  diff
   <dbl>  <dbl> <dbl>
1    8.6    6.9  -1.7

Visualicemos los datos

# especifico data, coordenada x y coordenada y
ggplot(data=ev_data,aes(x=date,y=mortalidad_infantil))+
  # capa de puntos y lineas
  geom_point()+
  geom_line()+
  # labels
  labs(title="Mortalidad Infantil en Argentina entre 1990-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.")

Visualicemos los datos

Veamos cual era la tendencia

Tomo la decisión de usar la tendencia los datos de la gestión anterior: 2015-2019.1

\[ Y_{t}=\alpha+\beta_1 T+\mu_t \qquad para \quad t\in(2015-19) \]

# fijo modelo 
modelo<-lm(mortalidad_infantil~date, 
           data=subset(ev_data, date>=2015 & date<=2019))

# Añado predicciones a la data
ev_data$proyeccion <-predict(modelo,newdata = ev_data)

# Hago el plot (me enfoco en periodo 2015-19)
ggplot(data=subset(ev_data,date>=2015 & date<=2019),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(aes(y=proyeccion,linetype="MCO\n(Tendencia)"))+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2019",
       subtitle = "Con ajuste de MCO",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

Veamos cual era la tendencia

Veamos cual era la tendencia

Después de ver la tasa de cambio en 15-19, la proyecto sobre 2020 y 2021. Pero hay un problema!

# Hago el plot (me enfoco en 2015 en adelante)
ggplot(data=subset(ev_data,date>=2015),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(aes(y=proyeccion,linetype="Tendencia"))+
  geom_vline(xintercept = 2019)+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2021",
       subtitle="Hay un problema, lo ven?",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

Veamos cual era la tendencia

Debo ajustar el punto de partida

Debo asegurarme de que la tendencia EMPIECE desde el mismo punto. Para eso:

\[ Y_{t}=\alpha+\beta_1 T+\beta_2I(T\geq2019)+\mu_t \quad para \quad t\in[2015-19] \]

# creo dummy
ev_data<-ev_data %>% mutate(is_2019=(date>=2019))
# ajusto modelo
modelo<-lm(mortalidad_infantil~date+is_2019, 
           data=subset(ev_data, date>=2015 & date<=2019))
  
# Cambio la prediccion en la data
ev_data$proyeccion2 <-predict(modelo,newdata = ev_data)

ggplot(data=subset(ev_data,date>=2015),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(aes(y=proyeccion2,linetype="Tendencia\ncon corte en\n2019"))+
  geom_vline(xintercept = 2019)+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

Debo ajustar el punto de partida

Puedo eliminar la parte previa de la tedencia

ggplot(data=subset(ev_data,date>=2015),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(data=subset(ev_data,date>=2019),
            aes(y=proyeccion2,linetype="Tendencia\ncon corte en\n2019"))+
  geom_vline(xintercept = 2019)+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

Puedo eliminar la parte previa de la tedencia

¿Cómo calcular el before-after tomando en cuenta la tendencia?

Ya tenemos una predicción del modelo

ev_data %>% 
  filter(date==2021) %>% 
  select(mortalidad_infantil, proyeccion2)  %>% 
  mutate(diff=mortalidad_infantil-proyeccion2) 
# A tibble: 1 × 3
  mortalidad_infantil proyeccion2   diff
                <dbl>       <dbl>  <dbl>
1                 6.9        7.20 -0.300

Proyecciones en 3 simples pasos

1. Ajusto un modelo en función de toda la data histórica 1

# creo dummy para ultimo ano
ev_data<-ev_data %>% 
  mutate(is_2021= (date>=2021))
# termino cuadratico en fecha para capturar desaceleracion
modelo_ii<-lm(mortalidad_infantil~date + I(date^2)+is_2021,
              data=ev_data) # datos de 1990-2021

tidy(modelo_ii)
# A tibble: 4 × 5
  term           estimate  std.error statistic     p.value
  <chr>             <dbl>      <dbl>     <dbl>       <dbl>
1 (Intercept) 36823.      5761.           6.39 0.000000642
2 date          -36.1        5.75        -6.27 0.000000877
3 I(date^2)       0.00883    0.00143      6.16 0.00000119 
4 is_2021TRUE    -1.66       0.658       -2.53 0.0174     

Proyecciones en 3 simples pasos

2. Creo una base de datos con la misma estructura (variables explicativas)

nueva_data_20_32<-data.frame(
  date=c(2000:2032)
  ) %>% 
  mutate(is_2021=(date>=2021))
tail(nueva_data_20_32,10)
   date is_2021
24 2023    TRUE
25 2024    TRUE
26 2025    TRUE
27 2026    TRUE
28 2027    TRUE
29 2028    TRUE
30 2029    TRUE
31 2030    TRUE
32 2031    TRUE
33 2032    TRUE

Proyecciones en 3 simples pasos

3. Uso augment_cols()

nueva_data_20_32<-
  augment_columns(modelo_ii,
                  newdata=nueva_data_20_32) %>% 
  select(date,is_2021,.fitted,.se.fit)
head(nueva_data_20_32,10)
# A tibble: 10 × 4
    date is_2021 .fitted .se.fit
   <int> <lgl>     <dbl>   <dbl>
 1  2000 FALSE      20.4   0.141
 2  2001 FALSE      19.6   0.145
 3  2002 FALSE      18.9   0.148
 4  2003 FALSE      18.2   0.151
 5  2004 FALSE      17.5   0.153
 6  2005 FALSE      16.8   0.154
 7  2006 FALSE      16.2   0.153
 8  2007 FALSE      15.6   0.151
 9  2008 FALSE      14.9   0.148
10  2009 FALSE      14.3   0.145

Visualicemos la proyección

ggplot(data=subset(ev_data,date>=2000 & date<=2021),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(color="Observado"))+
  geom_point(data=nueva_data_20_32,
            aes(y=.fitted))+
  geom_line(data=nueva_data_20_32,
            aes(y=.fitted,color="Proyeccion"), linetype="dashed")+
  geom_vline(xintercept = 2021)+
  labs(title="Mortalidad Infantil en Argentina entre 2000-2032",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       colour=NULL,
       y=NULL)

Visualicemos la proyección

Removamos el tramo anterior

ggplot(data=subset(ev_data,date>=2000),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(color="Observado"))+
  geom_point(data=subset(nueva_data_20_32,date>=2021),
            aes(y=.fitted))+
  geom_line(data=subset(nueva_data_20_32,date>=2021),
            aes(y=.fitted,color="Proyeccion"), linetype="dashed")+
  geom_vline(xintercept = 2021)+
  labs(title="Mortalidad Infantil en Argentina entre 2000-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       colour=NULL,
       y=NULL)

Removamos el tramo anterior

Usemos los intervalos de confianza!

Lo bueno de haberlo hecho con una regresión es que tenemos una medida de incertidumbre.

ggplot(data=subset(ev_data,date>=2010),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(color="Observado"))+
  geom_pointrange(data=subset(nueva_data_20_32,date>=2021),
                  aes(group=date,
                      x=date,
                      y=.fitted,
                      ymin = (.fitted-.se.fit),
                      ymax = (.fitted+.se.fit)))+
  geom_line(data=subset(nueva_data_20_32, date>=2021),
            aes(y=.fitted,color="Proyeccion"), linetype="dashed")+
  labs(title="Mortalidad Infantil en Argentina entre 2010-2032",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       colour=NULL,
       y=NULL)

Usemos los intervalos de confianza!

wbstats les puede ser muy útil

Ejemplo: Estoy investigando sobre pobreza y desempleo y quiero saber que datos tengo

# 'pobreza' OR 'desempleo' 
pobreza_desempleo <- wb_search(pattern = "pobreza|desempleo",cache = new_cache)

head(pobreza_desempleo)
# A tibble: 6 × 3
  indicator_id         indicator                                  indicator_desc
  <chr>                <chr>                                      <chr>         
1 1.0.HCount.1.90usd   Tasa de Incidencia de la Pobreza ($1.90 a… Tasa de Incid…
2 1.0.HCount.2.5usd    Tasa de Incidencia de la Pobreza ($2.50 a… Tasa de Incid…
3 1.0.HCount.Mid10to50 Tasa de Incidencia de la Clase Media ($10… Tasa de Incid…
4 1.0.HCount.Ofcl      Tasa Oficial de la Pobreza Moderada-Nacio… Tasa de Incid…
5 1.0.HCount.Poor4uds  Tasa de Incidencia de la Pobreza ($4 al d… Tasa de Incid…
6 1.0.HCount.Vul4to10  Tasa de incidencia de población Vulnerabl… Tasa de Incid…

Código para llevar

#1. librerias
library(tidyverse) # libreria muy usada para manipular los datos y hacer grficos
library(modelsummary)# para tablas
library(broom)       # Revisar modelos
library(wbstats)     # Datos actualizados del WB. Instalar: install.packages("wbstats")
library(janitor)     # Limpiar nombres de columnas

#2. datos de wbstats

# Ingles es default, pero puedo pedir español
new_cache <- wb_cache(lang = "es")

# Variables relacionadas a mortalidad
ev_vars<- wb_search(pattern = "tasa de mortalidad",cache = new_cache)

tail(ev_vars, 20)

# Puedes añadir varios paises, con minusculas, mayusculas, o abreviaciones
# Es valido ARG, Arg, Argentina, ArGenTina, etc
# Identifica todos los iso3c, iso2c, country, region_iso3c, admin_region_iso3c, admin_region, income_level

example_geos <- c("Argentina")
ev_data <- wb_data("SH.DYN.MORT", country = example_geos,
                    start_date = 1990, end_date = 2021) 
head(ev_data)

#3. cambios en mortalidad infantil 1

ev_data<-ev_data %>%
  # remuevo puntos y mayusc de los nombres
  janitor::clean_names() %>% 
  rename(mortalidad_infantil=sh_dyn_mort)

ev_data_19_21<-ev_data %>% 
  filter(date %in% c(2019,2021))

ev_data_19_21 %>% 
  select(date,mortalidad_infantil) %>% 
  pivot_wider(names_from = "date", 
              values_from = "mortalidad_infantil") %>% 
  mutate(diff= `2021`-`2019`)

ggplot(data=ev_data,aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line()+
  labs(title="Mortalidad Infantil en Argentina entre 1990-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.")

#4. Calculo respecto a tendencias

# fijo modelo 
modelo<-lm(mortalidad_infantil~date, 
           data=subset(ev_data, date>=2015 & date<=2019))

# Añado predicciones a la data
ev_data$proyeccion <-predict(modelo,newdata = ev_data)

# Hago el plot (me enfoco en periodo 2015-19)
ggplot(data=subset(ev_data,date>=2015 & date<=2019),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(aes(y=proyeccion,linetype="MCO\n(Tendencia)"))+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2019",
       subtitle = "Con ajuste de MCO",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

# Hago el plot (me enfoco en 2015 en adelante)
ggplot(data=subset(ev_data,date>=2015),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(aes(y=proyeccion,linetype="Tendencia"))+
  geom_vline(xintercept = 2019)+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2021",
       subtitle="Hay un problema, lo ven?",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

# creo dummy
ev_data<-ev_data %>% mutate(is_2019=(date>=2019))
# ajusto modelo
modelo<-lm(mortalidad_infantil~date+is_2019, 
           data=subset(ev_data, date>=2015 & date<=2019))
  
# Cambio la prediccion en la data
ev_data$proyeccion2 <-predict(modelo,newdata = ev_data)

ggplot(data=subset(ev_data,date>=2015),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(aes(y=proyeccion2,linetype="Tendencia\ncon corte en\n2019"))+
  geom_vline(xintercept = 2019)+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

# elimino la tendencia en tramo anterior
ggplot(data=subset(ev_data,date>=2015),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(linetype="Datos"))+
  geom_line(data=subset(ev_data,date>=2019),
            aes(y=proyeccion2,linetype="Tendencia\ncon corte en\n2019"))+
  geom_vline(xintercept = 2019)+
  labs(title="Mortalidad Infantil en Argentina entre 2015-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       linetype=NULL,
       y=NULL)

# calculo las diferencias en 2021
ev_data %>% 
  filter(date==2021) %>% 
  select(mortalidad_infantil, proyeccion2)  %>% 
  mutate(diff=mortalidad_infantil-proyeccion2) 

#5. Proyecciones a 2032

# creo dummy para ultimo ano
ev_data<-ev_data %>% 
  mutate(is_2021= (date>=2021))

# termino cuadratico en fecha para capturar desaceleracion
modelo_ii<-lm(mortalidad_infantil~date + I(date^2)+is_2021,
              data=ev_data) # datos de 1990-2021

tidy(modelo_ii)

# creo nuevos datos sinteticos
nueva_data_20_32<-data.frame(
  date=c(2000:2032)
  ) %>% 
  mutate(is_2021=(date>=2021))

# uso augment cols
nueva_data_20_32<-
  augment_columns(modelo_ii,
                  newdata=nueva_data_20_32) %>% 
  select(date,is_2021,.fitted,.se.fit)

# visualizacion
ggplot(data=subset(ev_data,date>=2000),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(color="Observado"))+
  geom_point(data=subset(nueva_data_20_32,date>=2021),
            aes(y=.fitted))+
  geom_line(data=subset(nueva_data_20_32,date>=2021),
            aes(y=.fitted,color="Proyeccion"), linetype="dashed")+
  geom_vline(xintercept = 2021)+
  labs(title="Mortalidad Infantil en Argentina entre 2000-2021",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       colour=NULL,
       y=NULL)

#6. Proyecciones con CI
ggplot(data=subset(ev_data,date>=2010),
       aes(x=date,y=mortalidad_infantil))+
  geom_point()+
  geom_line(aes(color="Observado"))+
  geom_pointrange(data=subset(nueva_data_20_32,date>=2021),
                  aes(group=date,
                      x=date,
                      y=.fitted,
                      ymin = (.fitted-.se.fit),
                      ymax = (.fitted+.se.fit)))+
  geom_line(data=subset(nueva_data_20_32, date>=2021),
            aes(y=.fitted,color="Proyeccion"), linetype="dashed")+
  labs(title="Mortalidad Infantil en Argentina entre 2010-2032",
       caption = "Elaboración propia en base a datos del Banco Mundial.",
       colour=NULL,
       y=NULL)

Fin