8.5 Time Series Regression
Distributed Lag model using dynlm
package, which is useful for dynamic linear models and time series regressions. Lags or differences can directly be specified in the model formula.
The main function used to estimate our model is the dynlm(formula, data)
function. Within this function, d()
can be used to specify the difference in a variable and L()
can be used to compute the desired lag of the variable.
d(u, 1)
means to calculate the first difference in u
; L(g, 0:2)
denotes g
of the current period and the past two periods, \(g\), \(g_{-1}\), and \(g_{-2}\).
Note that data
must be either a data frame or zoo
object. xts
returns an error.
> library(dynlm)
# Finite Distributed Lag Models
> okun.lag2 <- dynlm(d(unemp, 1) ~ L(gGDP, 0:2), data = okun2.zoo) # lag 2
> okun.lag3 <- dynlm(d(unemp, 1) ~ L(gGDP, 0:3), data = okun2.zoo) # lag 3
# ARDL(1, 1)
> okun.ardl <- dynlm(d(unemp, 1) ~ L(d(unemp, 1), 1) + L(gGDP, 0:1), data = okun2.zoo)
> summary(okun.ardl)
Time series regression with "zoo" data:
Start = 1948 Q3, End = 2025 Q1
Call:
dynlm(formula = d(unemp, 1) ~ L(d(unemp, 1), 1) + L(gGDP, 0:1),
data = okun2.zoo)
Residuals:
Min 1Q Median 3Q Max
-1.4662 -0.2198 -0.0218 0.1686 4.9875
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.42871 0.03769 11.374 < 2e-16 ***
L(d(unemp, 1), 1) -0.05640 0.05874 -0.960 0.337736
L(gGDP, 0:1)1 -0.43423 0.02390 -18.165 < 2e-16 ***
L(gGDP, 0:1)2 -0.11951 0.03575 -3.343 0.000932 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.4416 on 303 degrees of freedom
(0 observations deleted due to missingness)
Multiple R-squared: 0.5825, Adjusted R-squared: 0.5784
F-statistic: 140.9 on 3 and 303 DF, p-value: < 2.2e-16
8.5.1 Lag Polynomial
Let \(\rho(L)=1-\rho_1L\) and \(\beta(L)=\beta_0+\beta_1L.\) Now we have \(\psi(L)\) such at
\[ \rho(L)\psi(L)=\beta(L) . \]
We want to find \(\psi(L)=\rho(L)^{-1}\beta(L).\)
# Compute psi(L) = rho(L)^(-1) * beta(L)
lag_poly_solution <- function(rho1, beta0, beta1, n_terms = 5) {
# Expand (1 - rho1*L)^(-1) as a power series up to n_terms
# (1 - rho1*L)^(-1) = 1 + rho1*L + rho1^2*L^2 + ... + rho1^n*L^n
rho_inv <- sapply(0:n_terms, function(k) rho1^k)
# beta(L) = beta0 + beta1*L
# psi(L) = (1 + rho1*L + rho1^2*L^2 + ...)*(beta0 + beta1*L)
# = beta0*(1 + rho1*L + ...) + beta1*L*(1 + rho1*L + ...)
# = beta0*rho_inv + beta1*c(0, rho_inv[1:n_terms])
psi <- beta0 * rho_inv
psi <- psi + beta1 * c(0, rho_inv[1:n_terms])
# Return coefficients: psi0 + psi1*L + psi2*L^2 + ...
names(psi) <- paste0("L^", 0:n_terms)
return(psi)
}
# Example usage:
psi_coef <- lag_poly_solution(rho1 = 0.5, beta0 = 1, beta1 = 2, n_terms = 20)
psi_coef
## L^0 L^1 L^2 L^3 L^4 L^5
## 1.000000e+00 2.500000e+00 1.250000e+00 6.250000e-01 3.125000e-01 1.562500e-01
## L^6 L^7 L^8 L^9 L^10 L^11
## 7.812500e-02 3.906250e-02 1.953125e-02 9.765625e-03 4.882812e-03 2.441406e-03
## L^12 L^13 L^14 L^15 L^16 L^17
## 1.220703e-03 6.103516e-04 3.051758e-04 1.525879e-04 7.629395e-05 3.814697e-05
## L^18 L^19 L^20
## 1.907349e-05 9.536743e-06 4.768372e-06
Plot the lag polynomial coefficients:
library(tidyverse)
psi_df <- tibble(
lag = 1:21,
coef = psi_coef
)
# Bar plot
ggplot(psi_df, aes(x = lag, y = coef)) +
geom_bar(stat = "identity", fill = "steelblue") +
labs(x = "Lag", y = expression(psi[L]), title = "Lag Polynomial Coefficients") +
theme_minimal()