Aplicación 2.2: Regresiones con datos de series temporales

Consumo privado en España

En esta aplicación se estimará una función de consumo de tipo Keynesiano agregada (para un consumidor representativo), usando datos de series temporales para España del período 1964-2022:

\[C_{t} = \beta_1 + \beta_2 Y_{t} + e_{t}\]

donde \(C\) representa el consumo privado (gasto en consumo final de los hogares e instituciones privadas sin fines de lucro al servicio de los hogares -ISFLSH-, en millones de € constantes de 2015), e \(Y\) es la renta (renta disponible bruta de los hogares e ISFLSH, en millones de € constantes de 2015).

Desde el punto de vista técnico, el objetivo principal del ejemplo es la introducción de las principales funciones y librerías especializadas de R y Python para regresiones con series temporales.

Code
# Lectura de librerías
library(tidyverse)
# Lectura de datos
CONS_ESP <- read_csv("data/CONS_ESP_ts.csv")
head(CONS_ESP)
# A tibble: 6 × 3
  Date             C       Y
  <date>       <dbl>   <dbl>
1 1964-12-31 164361. 175820.
2 1965-12-31 174522. 182783.
3 1966-12-31 186740. 195919.
4 1967-12-31 196348. 201365.
5 1968-12-31 207885. 220639.
6 1969-12-31 225025. 236631.
Code
tail(CONS_ESP)
# A tibble: 6 × 3
  Date             C       Y
  <date>       <dbl>   <dbl>
1 2017-12-31 666835. 710941.
2 2018-12-31 678168. 721103.
3 2019-12-31 685567. 749681.
4 2020-12-31 601782. 733411.
5 2021-12-31 644511. 749752.
6 2022-12-31 674961. 732679.
Code
# Asignación del formato de series temporales
# (https://cran.r-project.org/web/views/TimeSeries.html)
#
# Aquí se usará la clase básica "ts", válida para series temporales 
# regulares (espaciadas de forma homogénea en el tiempo).
# Pueden usarse otras clases más generales, siendo las más usadas:
# "zoo": https://cran.r-project.org/web/packages/zoo/index.html 
# "xts": https://github.com/joshuaulrich/xts
# "tsibble": https://github.com/robjhyndman/fpp3package
# Ver anexo para una demostración sobre el <<tidyverts>>, 
# el complemento al tidyverse para el análisis de series temporales.
#
ts_CONS_ESP <- ts(CONS_ESP[,2:3], start=c(1964), end = c(2022))
#
# Estadística descriptiva
summary(ts_CONS_ESP)
       C                Y         
 Min.   :164361   Min.   :175820  
 1st Qu.:329035   1st Qu.:342111  
 Median :442941   Median :468111  
 Mean   :454270   Mean   :490163  
 3rd Qu.:618063   3rd Qu.:680903  
 Max.   :693029   Max.   :749752  
Code
# Gráficas
g1 <- ggplot(data = CONS_ESP, aes(x = Date)) +
  geom_line(aes(y = C)) +
  labs(y = "Consumo privado en España (millones €)", x = "Año")
g1

Code
g2 <- ggplot(data = CONS_ESP, aes(x = Date)) +
  geom_line(aes(y = Y)) +
  labs(y = "Renta disponible en España (millones €)", x = "Año")
g2

Code
# Diagrama de puntos con línea de regresión
g3 <- ggplot(CONS_ESP, aes(x = Y, y = C)) + 
               geom_point() +  
               stat_smooth(method = lm) +  
               labs(x = "Renta disponible",y = "Consumo privado")
g3

Code
# Regresión por MCO
lin_model <- lm (formula = C ~ Y, data = ts_CONS_ESP)
summary(lin_model)

Call:
lm(formula = C ~ Y, data = ts_CONS_ESP)

Residuals:
   Min     1Q Median     3Q    Max 
-65322  -6950   1132   8820  24670 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 2.539e+04  5.376e+03   4.723 1.56e-05 ***
Y           8.750e-01  1.025e-02  85.366  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 14690 on 57 degrees of freedom
Multiple R-squared:  0.9922,    Adjusted R-squared:  0.9921 
F-statistic:  7287 on 1 and 57 DF,  p-value: < 2.2e-16
Code
# ANEXO: La  librería fpp3 y el tidyverts' (https://tidyverts.org/)
# La macro-librería `fpp3` contiene varias librerías específicas
# y otras generales, como `tidyverse` y  `lubridate`.
# La clase `tsibble` proporciona una infraestructura de datos para ordenar
# y manipular series temporales. Se pueden encontrar los detalles en las
# páginas webs https://tsibble.tidyverts.org/index.html y
# https://robjhyndman.com/publications/tsibble/.
# Toda la información de la librería fpp3 se encuentra en:
# https://github.com/robjhyndman/fpp3package. 
# El libro de texto que acompaña a esta librería es el siguiente:
# FORECASTING: PRINCIPLES AND PRACTICE -> https://otexts.com/fpp3/.
#
# NOTA:
# Existen otras librerías especializadas en el análisis de series temporales, 
# como `TSstudio` (https://ramikrispin.github.io/TSstudio/),
# `timetk` (https://business-science.github.io/timetk/) o 
# `tsbox`(https://docs.ropensci.org/tsbox/).
#
library(fpp3) 
Registered S3 method overwritten by 'tsibble':
  method               from 
  as_tibble.grouped_df dplyr
── Attaching packages ──────────────────────────────────────────── fpp3 1.0.1 ──
✔ tsibble     1.1.6     ✔ feasts      0.4.1
✔ tsibbledata 0.4.1     ✔ fable       0.4.1
── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
✖ lubridate::date()    masks base::date()
✖ dplyr::filter()      masks stats::filter()
✖ tsibble::intersect() masks base::intersect()
✖ tsibble::interval()  masks lubridate::interval()
✖ dplyr::lag()         masks stats::lag()
✖ tsibble::setdiff()   masks base::setdiff()
✖ tsibble::union()     masks base::union()
Code
# Creación del objeto tsibble
CONS_ESP_ts <-  CONS_ESP[,2:3] %>%
  mutate(Year = 1964:2022) %>%
  as_tsibble(index = Year)
# Gráficas individuales
CONS_ESP_ts %>% autoplot(C) +
  ggtitle("Consumo privado en España") +
  ylab("Millones €") + xlab("Año")

Code
CONS_ESP_ts %>% autoplot(Y) +
  ggtitle("Renta disponible en España") +
  ylab("Millones €") + xlab("Año")

Code
# Diagrama de puntos junto con la recta de regresión estimada
CONS_ESP_ts %>%
  ggplot(aes(x=Y, y=C)) +
  ylab("Consumo privado") +
  xlab("Renta disponible") +
  geom_point() +
  geom_smooth(method="lm", se=FALSE)
`geom_smooth()` using formula = 'y ~ x'

Code
# Regresión por MCO
CONS_ESP_ts %>%
  model(tslm = TSLM(C ~ Y)) %>%
  report()
Series: C 
Model: TSLM 

Residuals:
   Min     1Q Median     3Q    Max 
-65322  -6950   1132   8820  24670 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 2.539e+04  5.376e+03   4.723 1.56e-05 ***
Y           8.750e-01  1.025e-02  85.366  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 14690 on 57 degrees of freedom
Multiple R-squared: 0.9922, Adjusted R-squared: 0.9921
F-statistic:  7287 on 1 and 57 DF, p-value: < 2.22e-16
Code
# Lectura de librerías
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.formula.api as smf
# Lectura de datos 
# (al introducir la opción index_col se está asignando en este caso
# de forma implícita un formato temporal para el resto de columnas)
CONS_ESP = pd.read_csv("data/CONS_ESP_ts.csv", index_col=0)
# (al introducir la opción index_col se está asignando en este caso
# de forma implícita un formato temporal para el resto de columnas)
#
# Asignación del formato temporal 
# (https://pandas.pydata.org/docs/user_guide/timeseries.html)
# Un análisis detallado puede encontrarse en la siguiente página web:
# https://jakevdp.github.io/PythonDataScienceHandbook/
# 03.11-working-with-time-series.html
ts_CONS_ESP = pd.read_csv("data/CONS_ESP_ts.csv", 
parse_dates=['Date'], index_col='Date')
ts_CONS_ESP.head()
                        C              Y
Date                                    
1964-12-31  164360.565116  175819.627074
1965-12-31  174521.522473  182783.279618
1966-12-31  186740.485052  195918.543262
1967-12-31  196347.846128  201364.508921
1968-12-31  207884.976097  220638.674259
Code
ts_CONS_ESP.tail()
                        C              Y
Date                                    
2018-12-31  678168.472101  721102.640419
2019-12-31  685567.322159  749681.277625
2020-12-31  601782.445267  733411.116791
2021-12-31  644511.362421  749751.796026
2022-12-31  674960.899465  732678.649099
Code
# Estadística descriptiva
ts_CONS_ESP.describe()
                   C              Y
count      59.000000      59.000000
mean   454270.117905  490163.324114
std    165346.490515  188238.913008
min    164360.565116  175819.627074
25%    329034.893784  342110.756619
50%    442940.762635  468111.433640
75%    618063.297097  680903.206704
max    693029.305659  749751.796026
Code
# Gráficas
plt.plot(ts_CONS_ESP["C"])
plt.xlabel("Año")
plt.ylabel("Consumo privado en España (millones €)")
plt.show()

Code
plt.plot(ts_CONS_ESP["Y"])
plt.xlabel("Año")
plt.ylabel("Renta disponible en España (millones €)")
plt.show()

Code
# Diagrama de puntos con línea de regresión
reg = smf.ols(formula = "C ~ Y", data = ts_CONS_ESP)
res = reg.fit()
plt.scatter(ts_CONS_ESP["Y"], ts_CONS_ESP["C"], color = "black")
plt.plot(ts_CONS_ESP["Y"], res.fittedvalues, color = "blue")
plt.xlabel("Renta disponible")
plt.ylabel("Consumo privado")
plt.show()

Code
# Regresión por MCO
model = smf.ols(formula = "C ~ Y", data = ts_CONS_ESP)
lin_model = model.fit()
print(lin_model.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      C   R-squared:                       0.992
Model:                            OLS   Adj. R-squared:                  0.992
Method:                 Least Squares   F-statistic:                     7287.
Date:                Sun, 09 Feb 2025   Prob (F-statistic):           7.70e-62
Time:                        13:04:52   Log-Likelihood:                -648.82
No. Observations:                  59   AIC:                             1302.
Df Residuals:                      57   BIC:                             1306.
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept   2.539e+04   5375.895      4.723      0.000    1.46e+04    3.62e+04
Y              0.8750      0.010     85.366      0.000       0.854       0.895
==============================================================================
Omnibus:                       32.296   Durbin-Watson:                   0.950
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               99.304
Skew:                          -1.504   Prob(JB):                     2.73e-22
Kurtosis:                       8.599   Cond. No.                     1.47e+06
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.47e+06. This might indicate that there are
strong multicollinearity or other numerical problems.