Discussion 3

Author

Aryamani Boruah

Published

February 11, 2026

Introduction

This analysis examines three time series datasets to assess stationarity, identify underlying patterns through ACF/PACF analysis, and decompose the series into trend, seasonal, and random components.

Time Series Selected: 1. Unemployment Rate 2. Consumer Price Index (CPI) - Inflation 3. Housing Starts

# Load required libraries
library(fredr)        # FRED data
library(tseries)      # ADF and KPSS tests
library(forecast)     # Time series forecasting
library(ggplot2)      # Visualization
library(gridExtra)    # Multiple plots
library(stats)        # Decomposi(
# Set FRED API key
fredr_set_key("8631a4e57900a09405dcb79f9488dff4")
# Download data from FRED
# Time Series 1: Unemployment Rate (monthly)
unrate <- fredr(
  series_id = "UNRATE",
  observation_start = as.Date("2000-01-01"),
  observation_end = as.Date("2023-12-31")
)

# Time Series 2: Consumer Price Index (monthly)
cpi <- fredr(
  series_id = "CPIAUCSL",
  observation_start = as.Date("2000-01-01"),
  observation_end = as.Date("2023-12-31")
)

# Time Series 3: Housing Starts (monthly)
housing <- fredr(
  series_id = "HOUST",
  observation_start = as.Date("2000-01-01"),
  observation_end = as.Date("2023-12-31")
)

# Convert to time series objects
unrate_ts <- ts(unrate$value, start = c(2000, 1), frequency = 12)
cpi_ts <- ts(cpi$value, start = c(2000, 1), frequency = 12)
housing_ts <- ts(housing$value, start = c(2000, 1), frequency = 12)

Part 1: Stationarity Analysis

1.1 Time Series 1: Unemployment Rate

Visual Inspection

plot(unrate_ts, 
     main = "U.S. Unemployment Rate (2000-2023)",
     ylab = "Unemployment Rate (%)",
     xlab = "Year",
     col = "darkblue",
     lwd = 2)

Observations: - The series shows clear fluctuations with peaks during recessions (2008-2009, 2020) - Mean appears to vary over time (non-constant) - Variance seems relatively stable

Formal Stationarity Tests

ADF Test (Augmented Dickey-Fuller)

adf_result <- adf.test(unrate_ts)
print(adf_result)

    Augmented Dickey-Fuller Test

data:  unrate_ts
Dickey-Fuller = -2.3169, Lag order = 6, p-value = 0.4426
alternative hypothesis: stationary

ADF Test Interpretation:

  • Null Hypothesis: The time series has a unit root (is NOT stationary)
  • Alternative Hypothesis: The time series is stationary
  • Decision:
    • p-value = 0.4426
    • Since p-value > 0.05, we FAIL TO REJECT the null hypothesis
    • Conclusion: The unemployment rate series is NOT stationary

KPSS Test

kpss_result <- kpss.test(unrate_ts)
print(kpss_result)

    KPSS Test for Level Stationarity

data:  unrate_ts
KPSS Level = 0.62105, Truncation lag parameter = 5, p-value = 0.02072

KPSS Test Interpretation:

  • Null Hypothesis: The time series IS stationary (opposite of ADF!)
  • Alternative Hypothesis: The time series is NOT stationary
  • Decision:
    • p-value = 0.0207
    • Since p-value < 0.05, we REJECT the null hypothesis
    • Conclusion: The unemployment rate series is NOT stationary

Stationarity Conditions

Based on both tests, the unemployment rate series violates the following stationarity condition(s):

  • Constant Mean: The mean changes over time due to economic cycles
  • The series exhibits trend-like behavior during recession and recovery periods

1.2 Time Series 2: Consumer Price Index (CPI)

Visual Inspection

plot(cpi_ts, 
     main = "U.S. Consumer Price Index (2000-2023)",
     ylab = "CPI (Index)",
     xlab = "Year",
     col = "darkred",
     lwd = 2)

Observations: - Clear upward trend over time - Non-constant mean (increasing) - Appears to have increasing variance (heteroskedasticity)

Formal Stationarity Tests

ADF Test

adf_result_cpi <- adf.test(cpi_ts)
print(adf_result_cpi)

    Augmented Dickey-Fuller Test

data:  cpi_ts
Dickey-Fuller = -0.03093, Lag order = 6, p-value = 0.99
alternative hypothesis: stationary

ADF Test Interpretation:

  • Null Hypothesis: The time series has a unit root (is NOT stationary)
  • Decision: p-value = 0.99
  • Conclusion: FAIL TO REJECT the null hypothesis. Series is NOT stationary.

KPSS Test

kpss_result_cpi <- kpss.test(cpi_ts)
print(kpss_result_cpi)

    KPSS Test for Level Stationarity

data:  cpi_ts
KPSS Level = 4.6136, Truncation lag parameter = 5, p-value = 0.01

KPSS Test Interpretation:

  • Null Hypothesis: The time series IS stationary
  • Decision: p-value = 0.01
  • Conclusion: REJECT the null hypothesis. Series is NOT stationary.

Stationarity Conditions Violated

The CPI series violates:

  • Constant Mean: Strong upward trend over time
  • Constant Variance: Variance appears to increase with the level
  • This is a classic non-stationary series requiring differencing or log transformation

1.3 Time Series 3: Housing Starts

Visual Inspection

plot(housing_ts, 
     main = "U.S. Housing Starts (2000-2023)",
     ylab = "Housing Starts (Thousands)",
     xlab = "Year",
     col = "darkgreen",
     lwd = 2)

Observations: - Shows cyclical patterns with sharp decline during 2008 financial crisis - Possible seasonal patterns - Variance changes over time

Formal Stationarity Tests

ADF Test

adf_result_housing <- adf.test(housing_ts)
print(adf_result_housing)

    Augmented Dickey-Fuller Test

data:  housing_ts
Dickey-Fuller = -1.0389, Lag order = 6, p-value = 0.9311
alternative hypothesis: stationary

ADF Test Interpretation:

  • Null Hypothesis: The time series has a unit root (is NOT stationary)
  • Decision: p-value = 0.9311
  • Conclusion: FAIL TO REJECT the null hypothesis. Series is NOT stationary.

KPSS Test

kpss_result_housing <- kpss.test(housing_ts)
print(kpss_result_housing)

    KPSS Test for Level Stationarity

data:  housing_ts
KPSS Level = 1.1682, Truncation lag parameter = 5, p-value = 0.01

KPSS Test Interpretation:

  • Null Hypothesis: The time series IS stationary
  • Decision: p-value = 0.01
  • Conclusion: REJECT the null hypothesis. Series is NOT stationary.

Stationarity Conditions Violated

The housing starts series violates:

  • Constant Mean: Shows economic cycle patterns
  • Possible seasonality: Construction has seasonal patterns
  • Mean and variance both change over time

Part 2: ACF and PACF Analysis

For ACF and PACF analysis, we first need to make the series stationary through differencing.

2.1 Unemployment Rate - ACF/PACF

Make Series Stationary

# First difference
unrate_diff <- diff(unrate_ts)

# Plot differenced series
plot(unrate_diff,
     main = "Differenced Unemployment Rate",
     ylab = "Change in Unemployment Rate",
     xlab = "Year",
     col = "darkblue",
     lwd = 2)

# Verify stationarity after differencing
adf.test(unrate_diff)

    Augmented Dickey-Fuller Test

data:  unrate_diff
Dickey-Fuller = -7.5525, Lag order = 6, p-value = 0.01
alternative hypothesis: stationary

ACF and PACF Plots

par(mfrow = c(2, 1))
acf(unrate_diff, main = "ACF: Differenced Unemployment Rate", lag.max = 40)
pacf(unrate_diff, main = "PACF: Differenced Unemployment Rate", lag.max = 40)

par(mfrow = c(1, 1))

Interpretation:

  • ACF Pattern:
    • Shows significant autocorrelation at lag 1
    • Gradual decay suggests AR component
  • PACF Pattern:
    • Sharp cutoff after lag 1 or 2
    • Suggests AR(1) or AR(2) process
  • Conclusion: The differenced unemployment rate appears to follow an AR(1) or AR(2) process based on the PACF cutoff pattern.

2.2 Consumer Price Index - ACF/PACF

Make Series Stationary

# First difference (or log difference for CPI)
cpi_diff <- diff(log(cpi_ts))  # Log difference to handle changing variance

# Plot differenced series
plot(cpi_diff,
     main = "Log Differenced CPI (Inflation Rate)",
     ylab = "Log Difference",
     xlab = "Year",
     col = "darkred",
     lwd = 2)

# Verify stationarity
adf.test(cpi_diff)

    Augmented Dickey-Fuller Test

data:  cpi_diff
Dickey-Fuller = -4.9741, Lag order = 6, p-value = 0.01
alternative hypothesis: stationary

ACF and PACF Plots

par(mfrow = c(2, 1))
acf(cpi_diff, main = "ACF: Log Differenced CPI", lag.max = 40)
pacf(cpi_diff, main = "PACF: Log Differenced CPI", lag.max = 40)

par(mfrow = c(1, 1))

Interpretation:

  • ACF Pattern:
    • Shows significant spikes at multiple lags
    • Slow decay pattern
  • PACF Pattern:
    • Significant spike at lag 1
    • Quick cutoff after initial lags
  • Conclusion: The differenced CPI (inflation rate) shows characteristics of an AR(1) process, with possible additional MA components. The persistence in inflation is captured by the AR term.

2.3 Housing Starts - ACF/PACF

Make Series Stationary

# First difference
housing_diff <- diff(housing_ts)

# Plot differenced series
plot(housing_diff,
     main = "Differenced Housing Starts",
     ylab = "Change in Housing Starts",
     xlab = "Year",
     col = "darkgreen",
     lwd = 2)

# Verify stationarity
adf.test(housing_diff)

    Augmented Dickey-Fuller Test

data:  housing_diff
Dickey-Fuller = -6.6511, Lag order = 6, p-value = 0.01
alternative hypothesis: stationary

ACF and PACF Plots

par(mfrow = c(2, 1))
acf(housing_diff, main = "ACF: Differenced Housing Starts", lag.max = 40)
pacf(housing_diff, main = "PACF: Differenced Housing Starts", lag.max = 40)

par(mfrow = c(1, 1))

Interpretation:

  • ACF Pattern:
    • Shows seasonal spikes at lags 12, 24 (annual seasonality)
    • Suggests seasonal MA component
  • PACF Pattern:
    • Significant spikes at seasonal lags
    • Indicates AR component
  • Conclusion: Housing starts shows seasonal ARIMA characteristics with both AR and MA components at seasonal lags (12 months). This suggests a SARIMA model would be appropriate.

Part 3: Time Series Decomposition

3.1 Unemployment Rate Decomposition

# STL decomposition (more robust than classical)
unrate_stl <- stl(unrate_ts, s.window = "periodic")
plot(unrate_stl, main = "STL Decomposition: Unemployment Rate")

# Also show classical decomposition for comparison
unrate_decomp <- decompose(unrate_ts, type = "additive")
plot(unrate_decomp, col = "darkblue")

Key Takeaways:

  1. Trend Component:
    • Shows long-term economic cycles
    • Clear spikes during recessions (2008-2009, 2020 COVID)
    • Recovery periods show gradual decline
  2. Seasonal Component:
    • Relatively weak seasonal pattern
    • Some evidence of within-year patterns (possibly related to labor market dynamics)
  3. Random Component:
    • Contains irregular fluctuations
    • Some large residuals during crisis periods suggest trend doesn’t capture all patterns
  4. Impact on Stationarity:
    • The dominant trend component explains why the series is non-stationary
    • Removing trend would help achieve stationarity
    • Weak seasonality doesn’t significantly impact stationarity

3.2 Consumer Price Index Decomposition

# STL decomposition
cpi_stl <- stl(cpi_ts, s.window = "periodic")
plot(cpi_stl, main = "STL Decomposition: Consumer Price Index")

# Classical decomposition (multiplicative due to increasing variance)
cpi_decomp <- decompose(cpi_ts, type = "multiplicative")
plot(cpi_decomp, col = "darkred")

Key Takeaways:

  1. Trend Component:
    • Strong, consistent upward trend
    • Slight acceleration in recent years (inflation spike)
    • This is the dominant component
  2. Seasonal Component:
    • Very weak or negligible seasonality
    • CPI is adjusted for seasonal factors (seasonally adjusted data)
  3. Random Component:
    • Relatively small compared to trend
    • Some volatility during specific periods
  4. Impact on Stationarity:
    • The strong trend is the PRIMARY reason for non-stationarity
    • First differencing or log transformation needed to remove trend
    • Lack of strong seasonality simplifies the modeling process

3.3 Housing Starts Decomposition

# STL decomposition
housing_stl <- stl(housing_ts, s.window = "periodic")
plot(housing_stl, main = "STL Decomposition: Housing Starts")

# Classical decomposition
housing_decomp <- decompose(housing_ts, type = "multiplicative")
plot(housing_decomp, col = "darkgreen")

Key Takeaways:

  1. Trend Component:
    • Shows boom and bust cycles
    • Dramatic decline during 2008 financial crisis
    • Gradual recovery post-2010
    • Recent plateau or slight decline
  2. Seasonal Component:
    • STRONG seasonal pattern
    • Clear peaks in spring/summer (construction season)
    • Troughs in winter months
    • Consistent pattern across years
  3. Random Component:
    • Contains irregular shocks
    • Large residuals during crisis period
    • Generally well-behaved outside of crisis
  4. Impact on Stationarity:
    • Both trend AND seasonality contribute to non-stationarity
    • Would require:
      • Seasonal differencing (lag 12) to remove seasonality
      • First differencing to remove trend
    • Suggests SARIMA(p,1,q)(P,1,Q)₁₂ model structure

Summary and Conclusions

Overall Findings

Stationarity Results

Time Series ADF Test KPSS Test Stationary? Conditions Violated
Unemployment Rate [Result] [Result] [Yes/No] Varying mean
CPI [Result] [Result] No Strong trend, changing variance
Housing Starts [Result] [Result] [Yes/No] Trend + Seasonality

ACF/PACF Insights

  1. Unemployment Rate: AR(1) or AR(2) process after differencing
  2. CPI: AR(1) process with possible MA component
  3. Housing Starts: Seasonal ARIMA with components at lag 12

Decomposition Insights

  1. Unemployment Rate:
    • Trend-dominated with weak seasonality
    • Economic cycles clearly visible
  2. CPI:
    • Pure trend with negligible seasonality
    • Strongest non-stationarity due to persistent upward movement
  3. Housing Starts:
    • Strong seasonal AND trend components
    • Most complex series requiring both regular and seasonal differencing

Implications for Modeling

  • Unemployment: ARIMA(1,1,0) or ARIMA(2,1,0) likely appropriate
  • CPI: ARIMA(1,1,0) with possible MA term
  • Housing Starts: SARIMA(p,1,q)(P,1,Q)₁₂ needed to capture seasonality

References


Session Info

sessionInfo()
R version 4.5.1 (2025-06-13)
Platform: aarch64-apple-darwin20
Running under: macOS Sonoma 14.5

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] gridExtra_2.3   ggplot2_4.0.1   forecast_9.0.0  tseries_0.10-59
[5] fredr_2.1.0    

loaded via a namespace (and not attached):
 [1] generics_0.1.4     lattice_0.22-7     digest_0.6.37      magrittr_2.0.4    
 [5] evaluate_1.0.5     grid_4.5.1         RColorBrewer_1.1-3 fastmap_1.2.0     
 [9] jsonlite_2.0.0     nnet_7.3-20        httr_1.4.7         scales_1.4.0      
[13] cli_3.6.5          rlang_1.1.6        withr_3.0.2        yaml_2.3.10       
[17] tools_4.5.1        parallel_4.5.1     dplyr_1.1.4        colorspace_2.1-2  
[21] curl_7.0.0         vctrs_0.6.5        R6_2.6.1           zoo_1.8-15        
[25] lifecycle_1.0.4    htmlwidgets_1.6.4  pkgconfig_2.0.3    urca_1.3-4        
[29] pillar_1.11.1      gtable_0.3.6       glue_1.8.0         quantmod_0.4.28   
[33] Rcpp_1.1.0         xfun_0.56          tibble_3.3.0       lmtest_0.9-40     
[37] tidyselect_1.2.1   rstudioapi_0.17.1  knitr_1.50         farver_2.1.2      
[41] htmltools_0.5.8.1  nlme_3.1-168       rmarkdown_2.29     xts_0.14.1        
[45] timeDate_4052.112  fracdiff_1.5-3     compiler_4.5.1     S7_0.2.1          
[49] quadprog_1.5-8     TTR_0.24.4