Curva de Phillips, ¿sigue siendo válida?

Author

Nosotros

Intro

Estamos en el tercer día del curso de Introducción a Quarto y estamos practicando cómo hacer un tutorial. Como algunos de los asistentes al curso es posible que no sepan mucho R, vamos a replicar y ampliar este ejemplo.

Marco teórico

Nos da un poco igual pero el gráfico de @ThomIvar hace referencia a la curva de Phillips que según la Wikipedia es:

La curva de Phillips, en macroeconomía, representa una curva empírica de pendiente negativa que relaciona la tasa de inflación y la tasa de desempleo. – Articulo de la Wiki aquí

Abajo tienes el gráfico que ilustra la Curva de Phillips en la Wikipedia:

Curva de Phillips en la Wikipedia

Por mucho que me empeñe yo, \(y_{t}=A_{1}y_{t-1}+A_{2}y_{t-2}+v_{t}\) no es la ecuación de la Curva de Phillips. Tampoco esta:

\[A(L)=(I_{K}-A_{1}L^{1}-A_{2}L^{2}-...-A_{p}L^{p})\]

Datos

Necesitamos datos de inflación y de tasa de desempleo. Vamos a usar los mimos datos que en el ejemplo original pero actualizados a 2023-06-21. Los datos provienen de la OCDE.

Antes de iniciar el análisis cargamos los paquetes de R que usaremos, solo que no vas a ver el chunk en el output final porque hemos puesto #| include: false.

Inflación

Descargamos datos de inflación con este código:

url_inflation <- "https://stats.oecd.org/sdmx-json/data/DP_LIVE/.CPI.../OECD?contentType=csv&detail=code&separator=comma&csv-lang=en"
ruta_inflation <- "./datos/ocde/DP_LIVE_22032023113248591.csv"
ruta_inflation <- here::here("datos", "ocde", "DP_LIVE_22032023113248591.csv")
# curl::curl_download(url_inflation, ruta_inflation)

Desempleo

Descargamos datos de desempleo con este código:

url_unemployment <- "https://stats.oecd.org/sdmx-json/data/DP_LIVE/.HUR.../OECD?contentType=csv&detail=code&separator=comma&csv-lang=en"
ruta_unemployment <- here::here("datos", "ocde", "DP_LIVE_22032023114049606.csv")
# curl::curl_download(url_unemployment, ruta_unemployment)

Resultados

Importamos los datos al Global env de R:

inflation_orig    <- readr::read_csv(ruta_inflation)
unemployment_orig <- readr::read_csv(ruta_unemployment)

Trabajamos los datos:

#- seleccionamos datos ---------------------------------------------------------
inflation <- inflation_orig %>%
  dplyr::filter(FREQUENCY == "M" & MEASURE == "AGRWTH", SUBJECT == "TOT") %>%
  select(place = LOCATION, date = TIME, cpi = Value)

unemployment <- unemployment_orig %>%
  dplyr::filter(FREQUENCY == 'M', SUBJECT == 'TOT') %>%
  select(place = LOCATION, date = TIME, rate = Value)

#- fusionamos los 2 df's -------------------------------------------------------
df <- left_join(inflation, unemployment) %>%
       tidyr::drop_na() %>%
       dplyr::mutate(group = case_when(
           str_starts(date, "199") ~ "1991-1999",
           str_starts(date, "200") ~ "2000-2009",
           str_starts(date, "201") ~ "2010-2019",
           str_starts(date, "202") ~ ">= 2020",
           TRUE ~ "other" )) %>%
      dplyr::filter(group != "other")

Hacemos el plot de @ThomIvar. Primero el plot básico:

my_country <- c("G-7")  #- seleccionamos "país"
my_periodos <- c("2000-2009", "2010-2019") #- seleccionamos periodos

df_1p <- df %>%
  dplyr::filter(place == my_country) %>%
  dplyr::filter(group %in% my_periodos)


# -- make plot for 1 country
p0 <- ggplot(df_1p, aes(x = rate, y = cpi, group = group, color = group)) +
        geom_point(alpha = 0.5, size = 2.25)
p0

Y ahora el super-gráfico:

my_title <- glue::glue("What happened to the <b>Phillips Curve</b> in ", my_country  , "? (thanks to <b style='color:#fd5532'>@ThomIvar</b>)")

p1 <- p0 + geom_smooth(method = 'lm', se = FALSE, linetype = 2) +
  scale_color_manual(values = c('#d1495b', '#00798c')) +
  annotate('text', x = 5.5, y = 3.75, label = '2000-2009', color = '#d1495b',
           family = 'American Typewriter', fontface = 'bold') +
  annotate('text', x = 4.5, y = 0.75, label = '2010-2019', color = '#00798c',
           family = 'American Typewriter', fontface = 'bold') +
   labs(title = my_title,
       subtitle = "The Phillips curve is an economic concept that states that inflation
       and unemployment have an inverse relationship. However, in the <b style='color:#00798c'>
       last decade</b> this relationship appears to have vanished.",
       caption = '@ThomIvar • source: OECD (monthly, G7 countries)',
       x = 'Unemployment rate, %',
       y = 'Inflation rate, %') +
  theme_void() +
  theme(text = element_text('American Typewriter', color = 'grey30'),
    legend.position = 'none',
    plot.title = element_textbox_simple(size = 20, margin = margin(b = 0.15, unit = 'cm')),
    plot.subtitle = element_textbox_simple(size = 11, color = 'grey60',
                                           margin = margin(b = 0.25, unit = 'cm')),
    plot.background = element_rect(fill = '#fffef7', color = '#fffef7'),
    plot.caption = element_text(size = 10, color = 'grey80'),
    plot.margin = margin(1, 1, 1, 1, 'cm'),
    panel.grid = element_line(color = 'grey70', linetype = 'dotted'),
    axis.title = element_text(margin = margin(t = 0.2, r = 0.2, unit = 'cm'), color = 'grey50'),
    axis.title.y = element_text(angle = 90),
    axis.text = element_text(color = 'grey70', size = 9,
                             margin = margin(t = 0.1, r = 0.1, unit = 'cm')),
    axis.line = element_line(color = 'grey50'),
    axis.ticks = element_line(color = 'grey50', size = 0.6),
    axis.ticks.length = unit(0.10, 'cm'))

p1

Más resultados

Por hacer algo nuevo vamos a hacer un faceted-graph:

#- SEGUNDA parte (del script) --------------------------------------------------
#- hacemos el gráfico para varios países ---------------------------------------
my_paises <- c("ESP", "FRA", "GBR", "DEU", "USA", "JPN")
my_periodos <- c("2000-2009", "2010-2019") 

df_paises <- df %>%  
  dplyr::filter(place %in% my_paises) %>% 
  dplyr::filter(group %in% my_periodos)

#- plot feo para luego hacer un facetting
p0 <- ggplot(df_paises, aes(x = rate, y = cpi, color = group)) +
  geom_point(alpha = 0.5, size = 0.75) +
  geom_smooth(method = 'lm', se = FALSE, linetype = 1) +
  scale_color_manual(values = c(  '#d1495b', '#00798c', '#099205','#8e0592'))

#p0
#p0 +  facet_wrap(vars(place))

p1 <- p0 +
  facet_wrap(vars(place), scales = "free")  +
   labs(title = "What happened to the <b>Phillips Curve</b>? ",
       subtitle = "The Phillips curve is an economic concept that states that inflation
       and unemployment have a inverse relationship. However, we could find some exceptions for <b style='color:#d1495b'>
       2000-2009</b> decade, and for the  <b style='color:#00798c'>
       last decade (2010-2019) </b>.",
       caption = "@pjpv4444  (thanks to  @ThomIvar) • source: OECD (monthly, G7 countries)",
       x = 'Unemployment rate, %',
       y = 'Inflation rate, %') +
  theme_void() +
  theme(text = element_text('American Typewriter', color = 'grey30'),
    legend.position = 'none',
    plot.title = element_textbox_simple(size = 20, margin = margin(b = 0.15, unit = 'cm')),
    plot.subtitle = element_textbox_simple(size = 11, color = 'grey60',
                                           margin = margin(b = 0.25, unit = 'cm')),
    plot.background = element_rect(fill = '#fffef7', color = '#fffef7'),
    plot.caption = element_text(size = 10, color = 'grey80'),
    plot.margin = margin(1, 1, 1, 1, 'cm'),
    panel.grid = element_line(color = 'grey70', linetype = 'dotted'),
    axis.title = element_text(margin = margin(t = 0.2, r = 0.2, unit = 'cm'), color = 'grey50'),
    axis.title.y = element_text(angle = 90),
    axis.text = element_text(color = 'grey70', size = 9,
                             margin = margin(t = 0.1, r = 0.1, unit = 'cm')),
    axis.line = element_line(color = 'grey50'),
    axis.ticks = element_line(color = 'grey50', size = 0.6),
    axis.ticks.length = unit(0.10, 'cm'))


p1

Tablas

Nos falta hacer una tabla, así que, por ejemplo, hacemos tabla de la inflación en el último mes que tengamos datos.

#- data munging
inflation <- inflation_orig %>%
  dplyr::filter(FREQUENCY == "M") %>%
  dplyr::filter(MEASURE == "AGRWTH") %>%
  dplyr::mutate(fecha = lubridate::ym(TIME)) %>%
  select(pais = LOCATION, fecha, inflacion = Value, tipo_inf = SUBJECT)

#- incorporar region para filtrar grupos de países
zz <- countrycode::codelist %>%
  select(iso.name.en, region, region23, wb, fips, ioc, imf, iso2c, iso3c, ecb, eurostat, continent, eu28, un, un.region.name)

inflation <- left_join(inflation, zz, by = join_by(pais == iso3c) ) # %>% distinct(pais, .keep_all = TRUE)

#- solo Europa (q no sea Europa del Este) --------------------------------------
df <- inflation %>%
  dplyr::filter(un.region.name %in% c("Europe")) %>%
  dplyr::filter(!(region23 %in% c("Eastern Europe")))


my_title <- "Tasas de inflación interanual en Europa (febrero 2023)"
my_subtitle <- "Países europeos y <span style='color:#3569a4'> España </span> "

#- paso a ancho ----------------------------------------------------------------
df <- df %>%
  select(pais, iso.name.en, fecha, inflacion, tipo_inf) %>%
  pivot_wider(names_from = tipo_inf, values_from = inflacion)

#- banderas --------------------------------------------------------------------
df <- df %>% #- fips
  mutate(iso2 = countrycode::countrycode(sourcevar = pais, origin = "iso3c", destination = "iso2c", warn = FALSE)) %>%
  mutate(iso2 = tolower(iso2)) %>%
  mutate(flag_URL = glue::glue('https://hatscripts.github.io/circle-flags/flags/{iso2}.svg'))

#- selecciono fecha ------------------------------------------------------------
my_fecha <-  max(inflation$fecha)
my_fecha <-  "2023-02-01"

df <- df %>% dplyr::filter(fecha == my_fecha)

#- ordeno de + a - la inf. total -----------------------------------------------
df <- df %>% select(1,2, flag_URL, 3, 6, everything()) %>% arrange(desc(TOT), ENRG) %>% select(-iso2)

df <- df %>% mutate(FOOD = FOOD/max(FOOD))
  • Tabla con el paquete DT
df_DT <- df %>% select(-flag_URL)
DT::datatable(df_DT)
DT::datatable(df_DT, filter = 'top', extensions = "Scroller")
  • Ahora tabla chula
#- con gt: https://gt.rstudio.com/
#df <- df %>% mutate(across(where(is.numeric), \(x) round(x, digits = 2)))
tt_6 <- df %>%
  gt(rowname_col = "pais") %>%
  tab_header(title = my_title, subtitle = md(my_subtitle))  %>%
  tab_source_note(md("Fuente: datos proveniente de la [OCDE](http://www.oecd.org/)")) %>%
  gtExtras::gt_theme_nytimes() %>%
  gtExtras::gt_img_rows(flag_URL, height = 25) %>%
  gtExtras::gt_merge_stack(col2 = iso.name.en, col1 = pais) %>%
  tab_footnote(footnote = "Tasa de inflación eliminando el efecto de la energía y los alimentos",
               location = cells_column_labels(columns = TOT_FOODENRG)) %>%
  cols_label(TOT = md("**Total**"), ENRG = "Energética", FOOD = "Alimentos", TOT_FOODENRG = "Total sin ..." )  %>%
  cols_align(align = "center") %>%
  cols_align(align = "left", columns = fecha) %>%
  cols_width(columns = TOT ~ px(120)) %>%
  fmt_percent(columns = c(TOT, ENRG, FOOD, TOT_FOODENRG), scale_values = FALSE) %>%
  tab_style(style = cell_text(color = "#f97d64"),
            locations = cells_body(columns = TOT,
            rows = TOT >= mean(TOT))) %>%
  tab_style(style = cell_text(color = "#f97d64"),
            locations = cells_body(columns = FOOD,
            rows = FOOD >= mean(FOOD))) %>%
   tab_style(style = cell_text(color = "#f97d64"),
            locations = cells_body(columns = ENRG,
            rows = ENRG >= mean(ENRG))) %>%
   tab_style(style = cell_text(color = "#3569a4"),
            locations = cells_body(rows = pais == "ESP")) %>%
   data_color(columns = c(TOT_FOODENRG),
              colors = scales::col_numeric(palette = "Reds", domain = NULL))

#gtExtras::gt_plt_bar_pct(column = FOOD, scaled = TRUE, fill = "blue", background = "lightblue")


tt_6
Tasas de inflación interanual en Europa (febrero 2023)
Países europeos y España
flag_URL fecha Total Energética Alimentos Total sin ...1
LVA
Latvia
2023-02-01 20.26% 46.43% 0.84% 10.51%
LTU
Lithuania
2023-02-01 18.74% 29.21% 1.00% 12.17%
EST
Estonia
2023-02-01 17.55% 30.28% 0.84% 12.13%
AUT
Austria
2023-02-01 10.88% 26.52% 0.54% 8.61%
ISL
Iceland
2023-02-01 10.20% 14.58% 0.40% 9.47%
SVN
Slovenia
2023-02-01 9.28% 6.14% 0.61% 7.67%
ITA
Italy
2023-02-01 9.15% 28.20% 0.44% 4.79%
FIN
Finland
2023-02-01 8.80% 16.83% 0.54% 6.60%
DEU
Germany
2023-02-01 8.68% 19.98% 0.69% 5.86%
IRL
Ireland
2023-02-01 8.46% 29.30% 0.43% 5.56%
PRT
Portugal
2023-02-01 8.25% 1.94% 0.71% 7.21%
NLD
Netherlands (the)
2023-02-01 7.96% −1.07% 0.59% NA
DNK
Denmark
2023-02-01 7.60% 13.97% 0.49% 5.80%
BEL
Belgium
2023-02-01 6.62% −7.93% 0.56% 6.90%
NOR
Norway
2023-02-01 6.30% 12.44% 0.29% 5.60%
FRA
France
2023-02-01 6.28% 13.95% 0.52% 3.57%
GRC
Greece
2023-02-01 6.13% −5.22% 0.49% 6.34%
ESP
Spain
2023-02-01 6.03% −8.87% 0.55% 5.19%
LUX
Luxembourg
2023-02-01 4.31% −1.98% 0.43% 3.63%
CHE
Switzerland
2023-02-01 3.37% 16.65% 0.21% 2.03%
SWE
Sweden
2023-02-01 NA 11.97% 0.69% 10.50%
Fuente: datos proveniente de la OCDE
1 Tasa de inflación eliminando el efecto de la energía y los alimentos

Mapas

Volvemos a seleccionar datos

inflation <- inflation_orig %>%
  dplyr::filter(FREQUENCY == "M" & MEASURE == "AGRWTH", SUBJECT == "TOT") %>%
  select(place = LOCATION, date = TIME, cpi = Value)