Introduction

Nigeria as a developing nation has experienced irregular and unpredictable trends in its economic growth. This precarious unstable economic growth is regularly affected by domestic debt and social spending priorities.

World Bank (2018) considers social spending as a vital investment which is crucial in improving human capital, reducing poverty and sustainable development in the long run.

The financing of programs such as education and health that lead to economic growth may require borrowing wherefore leading to increased domestic debt (Adeoye, 2020).

Invariably, excessive domestic debt could lead to debt overhang where high levels of debt undermines an investor’s confidence, increasing inflation and reducing private sector investment thus stifling economic growth (Adeleye & Ogundipe 2021).

Aim

The study aims to determine the impact of domestic debt and social spending on economic growth in Nigeria

Research Questions

  1. What are the trends of domestic debt, social spending and economic growth in Nigeria?

  2. What is the association between domestic debt, social spending and economic growth in Nigeria?

  3. What is the direction of causality among domestic debt, social spending and economic growth in Nigeria?

Research Objectives

  1. Determine the trend of domestic debt, social spending and economic growth in Nigeria.

  2. To examine the association between domestic debt, social spending and economic growth in Nigeria.

  3. To evaluate the direction of causality among domestic debt, social spending and economic growth in Nigeria.

Importing necessary dataset

library(readr)
library(tidyverse)
#Load the data set
Main_Data <- read_csv("main_data.csv")

Descriptive Statistics

summary(Main_Data[, -1])
##       YEAR          EDUEXP          HLTHEXP         MILTEXP      
##  Min.   :2000   Min.   :0.3191   Min.   :2.491   Min.   :0.3484  
##  1st Qu.:2006   1st Qu.:0.3964   1st Qu.:3.321   1st Qu.:0.4329  
##  Median :2012   Median :0.4140   Median :3.582   Median :0.5059  
##  Mean   :2012   Mean   :0.4140   Mean   :3.652   Mean   :0.5545  
##  3rd Qu.:2018   3rd Qu.:0.4140   3rd Qu.:3.910   3rd Qu.:0.5792  
##  Max.   :2024   Max.   :0.5492   Max.   :5.054   Max.   :1.0127  
##      GDPGR              L               K               INT        
##  Min.   :-1.794   Min.   :17.54   Min.   : 6.542   Min.   : 3.268  
##  1st Qu.: 2.860   1st Qu.:17.69   1st Qu.:15.803   1st Qu.: 7.142  
##  Median : 5.308   Median :17.80   Median :21.434   Median : 7.850  
##  Mean   : 4.986   Mean   :17.79   Mean   :21.434   Mean   : 7.850  
##  3rd Qu.: 6.671   3rd Qu.:17.89   3rd Qu.:27.118   3rd Qu.: 8.995  
##  Max.   :15.329   Max.   :18.05   Max.   :34.110   Max.   :11.064  
##       INF             DMDper         DMDSERVper   
##  Min.   : 5.388   Min.   : 1.172   Min.   :0.641  
##  1st Qu.: 9.708   1st Qu.: 6.402   1st Qu.:0.986  
##  Median :11.869   Median : 8.946   Median :1.171  
##  Mean   :11.869   Mean   : 9.777   Mean   :1.316  
##  3rd Qu.:13.720   3rd Qu.:10.903   3rd Qu.:1.478  
##  Max.   :18.874   Max.   :25.355   Max.   :3.975
sapply(Main_Data[, -1], sd, na.rm = TRUE)
##       YEAR     EDUEXP    HLTHEXP    MILTEXP      GDPGR          L          K 
## 7.35980072 0.04900584 0.56560334 0.17106494 3.56863828 0.14108187 6.43092446 
##        INT        INF     DMDper DMDSERVper 
## 1.67996192 3.33758908 6.24248737 0.67392454
Analyzing the mean, median and standard deviation of the variables
  1. EDUEXP (Education Expenditure) Mean = 0.414, Median = 0.414 “The mean and median are almost identical, indicating symmetry.”

  2. HLTHEXP (Health Expenditure) Mean = 3.652, Median = 3.582 The mean is slightly higher than median. The variable is slightly right skewed (some high values pulling mean up).

  3. GDPGR (GDP Growth rate) Mean = 4.986, Median = 5.308 The median is higher than mean. It depicts that GDPGR is slightly left skewed (some low/negative growth years pulling mean down). SD = 3.57 economic growth fluctuated significantly (from -1.79% to 15.33%).

  4. DMDper (Domestic Debt): SD = 6.24 quite variable over years (from 1.17% to 25.36%).

  5. INT (Interest rate): SD = 1.68 moderate variation, less volatile than GDP growth or debt.

General inference from the data Education and health spending are relatively stable over 25 years. Military spending is low on average but slightly more variable. Debt and GDP growth are more volatile, which is typical in developing economies. Labor and capital percentages are quite stable, which is good for production function estimation.

Visualizing the data

library(ggplot2)
library(RColorBrewer)

# Listing the variables to be plotted
plot_vars <- c("DMDper", "EDUEXP", "HLTHEXP", "MILTEXP", "GDPGR", "INF", "INT")
# Reshaping the data
var_long <- Main_Data %>%
  pivot_longer(
    cols = all_of(plot_vars),
    names_to = "Indicator",
    values_to = "Value"
  ) %>%
  mutate(
    Indicator = recode(Indicator,
                       DMDper      = "Domestic Debt (% of GDP)",
                       DMDSERVper  = "Debt Servicing (% of GDP)",
                       EDUEXP      = "Education Expenditure (% of GDP)",
                       HLTHEXP     = "Health Expenditure (% of GDP)",
                       MILTEXP     = "Military Expenditure (% of GDP)",
                       GDPGR       = "GDP Growth Rate (%)",
                       INT         = "Interest Rate (%)",
                       INF         = "Inflation Rate (%)"
    )
  )


# First plot
# Line plot for the most important variables
ggplot(var_long, aes(x = YEAR, y = Value, color = Indicator, linetype = Indicator)) +
  geom_line(linewidth = 1) + # Use linewidth instead of size
  labs(
    title = "Trends Growth Rate Against Important Variables (2000-2024)",
    x = "Year",
    y = "Percentage Values",
    color = "Indicator Type",
    linetype = "Indicator Type" # Add a label for the linetype legend
  ) +
  theme_minimal() + 
  # Apply a color palette from RColorBrewer
  scale_color_brewer(palette = "Dark2")

#second plot
# Line plot for the most important variables with facet wrap
ggplot(var_long, aes(x = YEAR, y = Value, color = Indicator, linetype = Indicator)) +
  geom_line(linewidth = 1) + # Use linewidth instead of size
  labs(
    title = "Trends for each macroeconomic Variables (2000-2024)",
    x = "Year",
    y = "Percentage Values",
    color = "Indicator Type",
    linetype = "Indicator Type" # Add a label for the linetype legend
  ) +
  facet_wrap(~ Indicator, scales = "free_y") +
  theme_minimal()

# Box plot
ggplot(var_long,  aes(x = Indicator, y = Value, fill = Indicator)) +
  geom_boxplot()  +
  labs(
    title = "Boxplot of Economic Variables",
    x = "Indicator",
    y = "Value"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1))

correlation <- Main_Data %>%
  select(GDPGR, DMDper, DMDSERVper, EDUEXP, HLTHEXP, MILTEXP, INT, INF, L, K) %>% 
  cor(use = "pairwise.complete.obs", method = "pearson")
correlation
##                  GDPGR      DMDper  DMDSERVper     EDUEXP     HLTHEXP
## GDPGR       1.00000000 -0.28896957 -0.03311467  0.2852267 -0.02159254
## DMDper     -0.28896957  1.00000000 -0.02542679 -0.2348019 -0.23998365
## DMDSERVper -0.03311467 -0.02542679  1.00000000 -0.1571352  0.12041871
## EDUEXP      0.28522671 -0.23480193 -0.15713520  1.0000000 -0.14055603
## HLTHEXP    -0.02159254 -0.23998365  0.12041871 -0.1405560  1.00000000
## MILTEXP     0.20358754  0.27587331  0.04552661 -0.3355038 -0.21873539
## INT        -0.24302576  0.62342708 -0.02665086 -0.0757666 -0.30506419
## INF        -0.03974682  0.02963890 -0.12595964 -0.1233264  0.11423664
## L          -0.65373170  0.46923162 -0.15186796 -0.3657492 -0.05276444
## K           0.28878216 -0.31345528  0.34699004 -0.1942208  0.02833955
##                MILTEXP         INT         INF           L           K
## GDPGR       0.20358754 -0.24302576 -0.03974682 -0.65373170  0.28878216
## DMDper      0.27587331  0.62342708  0.02963890  0.46923162 -0.31345528
## DMDSERVper  0.04552661 -0.02665086 -0.12595964 -0.15186796  0.34699004
## EDUEXP     -0.33550382 -0.07576660 -0.12332636 -0.36574918 -0.19422076
## HLTHEXP    -0.21873539 -0.30506419  0.11423664 -0.05276444  0.02833955
## MILTEXP     1.00000000  0.22343628  0.12832309  0.12854477  0.18541801
## INT         0.22343628  1.00000000 -0.02162666  0.22940105 -0.23565731
## INF         0.12832309 -0.02162666  1.00000000 -0.16053389  0.17462100
## L           0.12854477  0.22940105 -0.16053389  1.00000000 -0.64238657
## K           0.18541801 -0.23565731  0.17462100 -0.64238657  1.00000000
# Visualizing the correlation
new_names <- c(
  DMDper      = "Domestic Debt (% of GDP)",
  DMDSERVper  = "Debt Servicing (% of GDP)",
  EDUEXP      = "Education Expenditure (% of GDP)",
  HLTHEXP     = "Health Expenditure (% of GDP)",
  MILTEXP     = "Military Expenditure (% of GDP)",
  GDPGR       = "GDP Growth Rate (%)",
  INT         = "Interest Rate (%)",
  INF         = "Inflation Rate (%)",
  L           = "Labour",
  K           = "Capital"
)

# Rename rows and columns of correlation matrix
colnames(correlation) <- new_names[colnames(correlation)]
rownames(correlation) <- new_names[rownames(correlation)]

library(corrplot)
## Warning: package 'corrplot' was built under R version 4.5.1
## corrplot 0.95 loaded
col <- colorRampPalette(c("#BB4444", "#EE9988", "#FFFFFF", "#77AADD", "#4477AA"))


corrplot(correlation, method = "color", col = col(200),  
         type = "upper", order = "hclust", 
         addCoef.col = "black", # Add coefficient of correlation
         tl.col = "black", tl.srt = 45, #Text label color and rotation
         tl.cex = 0.6,
         mar = c(0,0,2,0)   # add top margin for title
) 
  title("Correlation Plot of the Macroeconomic Variables")

Checking Multicollinearity

library(car)
# Fit a linear model with all independent variables predicting GDP growth
vif_model <- lm(GDPGR ~ EDUEXP + HLTHEXP + MILTEXP + INT + INF + DMDper + DMDSERVper + L + K, data = Main_Data)

# Compute VIF
vif(vif_model)
##     EDUEXP    HLTHEXP    MILTEXP        INT        INF     DMDper DMDSERVper 
##   2.051950   1.289622   1.352937   1.782450   1.170216   2.123118   1.248018 
##          L          K 
##   3.408970   3.231823

Variance Inflation Factor (VIF) measures how much a variable’s variance is inflated due to correlation with other independent variables: Rule of thumb: VIF < 5 → generally safe.

Conclusion: No severe multicollinearity detected (VIF < 5) among independent variables.

Stationarity

A stationary time series has statistical properties that do not change over time. that is, the mean is constant and Variance is constant.

Stationarity is important because many econometric models, including ARDL, assume stationarity and non-stationary data can produce spurious regression: results that look significant but are meaningless.

library(urca)
summary(ur.pp(Main_Data$DMDper, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -6.6750 -2.3718 -1.2667  0.9367 13.3359 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)   
## (Intercept)   4.0676     1.9524   2.083  0.04963 * 
## y.l1          0.6240     0.1954   3.193  0.00437 **
## trend         0.2912     0.1505   1.934  0.06665 . 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.299 on 21 degrees of freedom
## Multiple R-squared:  0.5804, Adjusted R-squared:  0.5404 
## F-statistic: 14.52 on 2 and 21 DF,  p-value: 0.0001097
## 
## 
## Value of test-statistic, type: Z-tau  is: -2.1029 
## 
##            aux. Z statistics
## Z-tau-mu              1.6240
## Z-tau-beta            2.0225
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$GDPGR, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.1626 -1.5518 -0.2976  1.6537  6.7479 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)   
## (Intercept)   4.5771     1.2146   3.768  0.00113 **
## y.l1          0.1136     0.2086   0.545  0.59178   
## trend        -0.3332     0.1071  -3.111  0.00529 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.609 on 21 degrees of freedom
## Multiple R-squared:  0.5322, Adjusted R-squared:  0.4877 
## F-statistic: 11.95 on 2 and 21 DF,  p-value: 0.0003431
## 
## 
## Value of test-statistic, type: Z-tau  is: -4.2321 
## 
##            aux. Z statistics
## Z-tau-mu              4.0140
## Z-tau-beta           -3.1144
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$EDUEXP, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.053100 -0.011415 -0.006476 -0.001281  0.134757 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)   
## (Intercept)  0.1669373  0.0730726   2.285  0.03285 * 
## y.l1         0.5978998  0.1749171   3.418  0.00259 **
## trend       -0.0009251  0.0012383  -0.747  0.46332   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.03971 on 21 degrees of freedom
## Multiple R-squared:  0.4253, Adjusted R-squared:  0.3706 
## F-statistic: 7.772 on 2 and 21 DF,  p-value: 0.002977
## 
## 
## Value of test-statistic, type: Z-tau  is: -2.3155 
## 
##            aux. Z statistics
## Z-tau-mu              2.2219
## Z-tau-beta           -0.7281
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$HLTHEXP, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.10551 -0.22274 -0.08029  0.14474  1.73257 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)   
## (Intercept)  2.288388   0.727632   3.145  0.00489 **
## y.l1         0.379936   0.196691   1.932  0.06701 . 
## trend       -0.009597   0.016071  -0.597  0.55679   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.5427 on 21 degrees of freedom
## Multiple R-squared:  0.1711, Adjusted R-squared:  0.09221 
## F-statistic: 2.168 on 2 and 21 DF,  p-value: 0.1393
## 
## 
## Value of test-statistic, type: Z-tau  is: -3.1049 
## 
##            aux. Z statistics
## Z-tau-mu              3.4241
## Z-tau-beta           -0.6720
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$MILTEXP, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.17514 -0.08483 -0.06074  0.03372  0.40725 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)  
## (Intercept) 0.272369   0.108806   2.503   0.0206 *
## y.l1        0.508438   0.188026   2.704   0.0133 *
## trend       0.001305   0.004647   0.281   0.7816  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.1565 on 21 degrees of freedom
## Multiple R-squared:  0.2676, Adjusted R-squared:  0.1979 
## F-statistic: 3.837 on 2 and 21 DF,  p-value: 0.03799
## 
## 
## Value of test-statistic, type: Z-tau  is: -2.6615 
## 
##            aux. Z statistics
## Z-tau-mu              2.3166
## Z-tau-beta            0.3148
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$INT, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.8910 -0.9323 -0.1032  0.8228  3.9659 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)   
## (Intercept)  5.45655    1.57933   3.455  0.00237 **
## y.l1         0.29193    0.19764   1.477  0.15450   
## trend        0.05969    0.04797   1.244  0.22708   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.58 on 21 degrees of freedom
## Multiple R-squared:  0.1886, Adjusted R-squared:  0.1113 
## F-statistic:  2.44 on 2 and 21 DF,  p-value: 0.1115
## 
## 
## Value of test-statistic, type: Z-tau  is: -3.5133 
## 
##            aux. Z statistics
## Z-tau-mu              4.0470
## Z-tau-beta            1.1128
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$INF, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -7.020 -1.281  0.091  1.488  5.844 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 10.99743    2.47667   4.440 0.000227 ***
## y.l1         0.09597    0.20042   0.479 0.636988    
## trend       -0.12428    0.09664  -1.286 0.212432    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3.234 on 21 degrees of freedom
## Multiple R-squared:  0.09244,    Adjusted R-squared:  0.006003 
## F-statistic: 1.069 on 2 and 21 DF,  p-value: 0.3612
## 
## 
## Value of test-statistic, type: Z-tau  is: -4.541 
## 
##            aux. Z statistics
## Z-tau-mu              3.8930
## Z-tau-beta           -1.2142
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$L, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.19789 -0.01292  0.00659  0.01996  0.06582 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)  
## (Intercept)  2.008681   8.426181   0.238    0.814  
## y.l1         0.887710   0.473831   1.873    0.075 .
## trend       -0.000465   0.009657  -0.048    0.962  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.051 on 21 degrees of freedom
## Multiple R-squared:  0.8675, Adjusted R-squared:  0.8549 
## F-statistic: 68.74 on 2 and 21 DF,  p-value: 6.078e-10
## 
## 
## Value of test-statistic, type: Z-tau  is: -0.5763 
## 
##            aux. Z statistics
## Z-tau-mu             -0.1369
## Z-tau-beta            3.7865
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181
summary(ur.pp(Main_Data$K, type = "Z-tau", model = "trend"))
## 
## ################################## 
## # Phillips-Perron Unit Root Test # 
## ################################## 
## 
## Test regression with intercept and trend 
## 
## 
## Call:
## lm(formula = y ~ y.l1 + trend)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -12.9047  -2.3758  -0.3846   2.3936   9.4812 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)  
## (Intercept)  10.4186     4.2025   2.479   0.0217 *
## y.l1          0.4929     0.1884   2.616   0.0161 *
## trend        -0.1536     0.1750  -0.878   0.3901  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.664 on 21 degrees of freedom
## Multiple R-squared:  0.4463, Adjusted R-squared:  0.3936 
## F-statistic: 8.465 on 2 and 21 DF,  p-value: 0.002014
## 
## 
## Value of test-statistic, type: Z-tau  is: -2.6053 
## 
##            aux. Z statistics
## Z-tau-mu              2.8670
## Z-tau-beta           -0.8663
## 
## Critical values for Z statistics: 
##                      1pct      5pct    10pct
## critical values -4.394203 -3.611847 -3.24181

For the Phillips-Perron (PP) Unit Root Test, the hypotheses are: Null Hypothesis: The series has a unit root (non-stationary) Alternative Hypothesis: The series is stationary

The test Statistic (Z-tau) is the main number for comparison.

Decision rule: If Z-tau < critical value: reject null (variable is stationary (I(0))) If Z-tau > critical value: fail to reject null (variable is non-stationary (needs differencing, I(1)))

Conclusion:

ARDL test

After confirming that the variables are stationary, ARDL test is then done. The full meaning of ARDL is Autoregressive Distributed Lag It has two key ideas: (A) Autoregressive part The dependent variable (GDPGR) depends on its own past values. An example of this in economic terms is:Today’s GDP growth depends on last year’s and two years ago’s growth (B) Distributed lag part GDP growth also depends on past values of explanatory variables. An example of this is: Education spending today may affect growth next year, not instantly

library(ARDL)
auto_ardl_model <- auto_ardl(GDPGR ~ EDUEXP + HLTHEXP + MILTEXP + INT + INF + DMDper + DMDSERVper + L + K, 
                             data = Main_Data, 
                             max_order = 2)
summary(auto_ardl_model)
##            Length Class      Mode   
## best_model 19     dynlm      list   
## best_order 10     -none-     numeric
## top_orders 11     data.frame list
auto_ardl_model$best_order # To know the best number of lags to be used.
##      GDPGR     EDUEXP    HLTHEXP    MILTEXP        INT        INF     DMDper 
##          1          1          2          2          2          1          1 
## DMDSERVper          L          K 
##          1          1          1
library(dynlm)
# Fit models with different lag lengths
Main_Data_ts <- ts(
  Main_Data[, -1],   # drop YEAR column
  start = 2000,
  end = 2024,
  frequency = 1
)

ardl_model <- dynlm(
  GDPGR ~
    L(GDPGR,1) +
    L(DMDper,1) +
    L(EDUEXP,1) +
    L(HLTHEXP,2) +
    L(MILTEXP,2) +
    L(INT,2) +
    L(INF,1),
  data = Main_Data_ts
)

summary(ardl_model)
## 
## Time series regression with "ts" data:
## Start = 2002, End = 2024
## 
## Call:
## dynlm(formula = GDPGR ~ L(GDPGR, 1) + L(DMDper, 1) + L(EDUEXP, 
##     1) + L(HLTHEXP, 2) + L(MILTEXP, 2) + L(INT, 2) + L(INF, 1), 
##     data = Main_Data_ts)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.5866 -1.9095  0.2256  1.5954  6.1525 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)  
## (Intercept)    -4.5112    11.1234  -0.406   0.6908  
## L(GDPGR, 1)     0.5247     0.2253   2.329   0.0342 *
## L(DMDper, 1)   -0.1731     0.1435  -1.206   0.2463  
## L(EDUEXP, 1)    2.4809    16.7482   0.148   0.8842  
## L(HLTHEXP, 2)  -0.1227     1.3038  -0.094   0.9263  
## L(MILTEXP, 2)   0.2310     4.8564   0.048   0.9627  
## L(INT, 2)       0.3783     0.4720   0.801   0.4354  
## L(INF, 1)       0.3938     0.2085   1.889   0.0783 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3.182 on 15 degrees of freedom
## Multiple R-squared:  0.5015, Adjusted R-squared:  0.2689 
## F-statistic: 2.156 on 7 and 15 DF,  p-value: 0.1003

Moving further, we test with the ARDL bounds test. What is the ARDL Bounds Test (conceptually)? The Bounds test answers one question only: Is there a long-run (cointegrating) relationship among the variables?

Hypotheses Null hypothesis (H₀):There is no long-run relationship (no cointegration) Alternative hypothesis (H₁):There is a long-run relationship (cointegration exists)

This test is done to check if the variables in the dataset has a long run effect on the dependent variable.

library(ARDL)
ardl_model2 <- ardl(
  GDPGR ~ DMDper + EDUEXP + HLTHEXP + MILTEXP + INT + INF,
  data = Main_Data_ts,
  order = c(1, 1, 1, 2, 2, 2, 1)
)
bounds_f_test(ardl_model2, case = 3)
## 
##  Bounds F-test (Wald) for no cointegration
## 
## data:  d(GDPGR) ~ L(GDPGR, 1) + L(DMDper, 1) + L(EDUEXP, 1) + L(HLTHEXP,     1) + L(MILTEXP, 1) + L(INT, 1) + L(INF, 1) + d(DMDper) +     d(EDUEXP) + d(HLTHEXP) + d(L(HLTHEXP, 1)) + d(MILTEXP) +     d(L(MILTEXP, 1)) + d(INT) + d(L(INT, 1)) + d(INF)
## F = 1.1722, p-value = 0.9003
## alternative hypothesis: Possible cointegration
## null values:
##    k    T 
##    6 1000

How to interpret the rest of the ARDL bounds test Condition Conclusion F < I(0) No cointegration F > I(1) Cointegration exists Between Inconclusive

The computed Bounds F-statistic of 1.17 is lower than the lower bound critical value of 2.45 at the 5% significance level. This implies that the null hypothesis of no cointegration cannot be rejected, indicating the absence of a long-run equilibrium relationship among the variables.

Short-run Model

short_run_model <- dynlm(
  d(GDPGR) ~ 
    L(GDPGR, 1) + # L(GDPGR,1) captures growth persistence
    
    d(DMDper) + #d() captures short-run effects
    d(EDUEXP) +
    d(HLTHEXP) +
    d(MILTEXP) +
    d(INT) +
    d(INF),
  data = Main_Data_ts
)

summary(short_run_model)
## 
## Time series regression with "ts" data:
## Start = 2001, End = 2024
## 
## Call:
## dynlm(formula = d(GDPGR) ~ L(GDPGR, 1) + d(DMDper) + d(EDUEXP) + 
##     d(HLTHEXP) + d(MILTEXP) + d(INT) + d(INF), data = Main_Data_ts)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.4398 -2.1168 -0.0454  1.9349  6.1303 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)  
## (Intercept)  0.75509    1.10252   0.685   0.5032  
## L(GDPGR, 1) -0.16703    0.18634  -0.896   0.3833  
## d(DMDper)    0.09709    0.16197   0.599   0.5573  
## d(EDUEXP)    8.62790   14.61895   0.590   0.5633  
## d(HLTHEXP)  -1.90538    1.06080  -1.796   0.0914 .
## d(MILTEXP)   4.68483    4.04185   1.159   0.2634  
## d(INT)      -0.39754    0.37576  -1.058   0.3058  
## d(INF)      -0.23467    0.13713  -1.711   0.1064  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.774 on 16 degrees of freedom
## Multiple R-squared:  0.5376, Adjusted R-squared:  0.3354 
## F-statistic: 2.658 on 7 and 16 DF,  p-value: 0.04996

Interpretation of the short-run model result

Is this short-run model acceptable? #### Overall model significance F-statistic p-value = 0.04996 This is significant at 5% Meaning: The explanatory variables jointly explain short-run movements in GDP growth.

Goodness of fit Adjusted R² = 0.335

Interpreting the coefficients
1. Lagged GDP Growth

Estimate = −0.167 p = 0.383 Interpretation: Previous year’s economic growth has a negative but statistically insignificant effect on current growth, indicating weak growth persistence in the Nigerian economy.

2. Domestic Debt

Estimate = +0.097 p = 0.557 Interpretation: A one-percentage-point increase in domestic debt leads to a 0.097 percentage-point increase in GDP growth in the short run; however, this effect is statistically insignificant. Economic meaning: Domestic borrowing does not immediately stimulate growth Supports the idea that funds may finance recurrent expenditure Or suffer from inefficiency and leakages

3. Education Expenditure

Estimate = +8.63 p = 0.563 Interpretation: Education spending has a positive but insignificant short-run effect on economic growth, reflecting the long gestation period required for human capital investment to impact output.

4. Health Expenditure

Estimate = −1.905 p = 0.091 (significant at 10%) Interpretation: Health expenditure exerts a negative and weakly significant short-run effect on economic growth. Why negative in the short run (Is social spending on health not meant to increase economic growth)? Health spending often rises during health crises and funds may go to salaries, imports of medical equipment, emergency consumption

5. Military Expenditure

Estimate = +4.68 p = 0.263 Interpretation: Military expenditure has a positive but insignificant short-run impact on economic growth, possibly reflecting security-related spending effects without strong productivity gains.

6. Interest Rate

Estimate = −0.398 p = 0.306 Interpretation: Rising interest rates negatively affect economic growth in the short run by increasing borrowing costs, although the effect is statistically insignificant.

7. Inflation

Estimate = −0.235 p = 0.106 (significant at 10%) Interpretation: Inflation exerts a negative and weakly significant short-run effect on economic growth, suggesting macroeconomic instability in the Nigerian economy.

In conclusion, domestic debt does not significantly promote economic growth in the short run in Nigeria.Borrowing alone is not enough. Growth depends on quality of spending, institutional efficiency, productive investment.

Post-Estimation tests

1. Serial Correlation (Breusch-Godfrey LM Test)

Hypothesis Null hypothesis: No serial correlation in residuals Alternative Hypothesis: Serial correlation present

library(lmtest)
bgtest(short_run_model, order = 1)  # order = lag of residuals
## 
##  Breusch-Godfrey test for serial correlation of order up to 1
## 
## data:  short_run_model
## LM test = 0.081391, df = 1, p-value = 0.7754

Result: p-value = 0.984 therefore fail to reject the null hypothesis Interpretation: Residuals are not serially correlated; model is reliable.

2. Heteroskedasticity (Breusch-Pagan-Godfrey)

Hypotheses:

Null hypothesis: No serial correlation in residuals Alternative Hypothesis: Serial correlation present

bptest(short_run_model)
## 
##  studentized Breusch-Pagan test
## 
## data:  short_run_model
## BP = 7.8403, df = 7, p-value = 0.3469

Result: BP = 7.8403, df = 7, p-value = 0.347 therefore fail to reject the null hypothesis Interpretation: Residuals have constant variance; no heteroskedasticity problem.

3. Normality of Residuals (Jarque-Bera / histogram)

Hypotheses: Null Hypothesis: Residuals are normally distributed Alternative Hypothesis: Residuals are not normally distributed

library(tseries)
jarque.bera.test(residuals(short_run_model))
## 
##  Jarque Bera Test
## 
## data:  residuals(short_run_model)
## X-squared = 1.1453, df = 2, p-value = 0.564
hist(residuals(short_run_model))

#Null: Residuals are normally distributed

Result: X² = 1.1453, df = 2, p-value = 0.564 therefore fail to reject the null hypothesis Interpretation: Residuals are approximately normal; t-tests and F-tests are valid.

4. Stability Test (CUSUM / CUSUMSQ)
resid_sr <- residuals(short_run_model)

library(strucchange)

cusum_test <- efp(
  resid_sr ~ 1,
  type = "Rec-CUSUM"
)

plot(cusum_test)

Interpretation: The cumulative sum of residuals remains within the 5% significance bounds, indicating that the model is structurally stable over the sample period.

5. Breusch–Godfrey Serial Correlation LM Test

What is Serial Correlation? Serial correlation means: The error term today is correlated with the error term yesterday. Null hypothesis: No serial correlation in the residuals Alternative hypothesis: Serial correlation exists

library(lmtest)

bg_test <- bgtest(short_run_model, order = 2)
bg_test
## 
##  Breusch-Godfrey test for serial correlation of order up to 2
## 
## data:  short_run_model
## LM test = 0.68434, df = 2, p-value = 0.7102

Interpretation: The Breusch–Godfrey Serial Correlation LM test was conducted to examine the presence of autocorrelation in the residuals of the short-run ARDL model. The result shows that the p-value (0.7102) exceeds the 5% significance level, indicating the absence of serial correlation. Hence, the model satisfies the classical regression assumption of independently distributed errors.

6. Breusch–Pagan–Godfrey Heteroskedasticity Test

What is Heteroskedasticity? In regression analysis, one key assumption of the Classical Linear Regression Model (CLRM) is that the variance of the error term is constant across all observations. This is called homoskedasticity.

This assumption fails when the variance of the errors changes over time or across observations.This problem is called heteroskedasticity.

Heteroskedasticity is important because although it does not bias the coefficients, it: Make standard errors unreliable Lead to wrong t-statistics Cause incorrect conclusions about significance So, even if coefficients look fine, inference becomes weak. That’s why examiners expect this test in ARDL studies.

Hypotheses:

Null Hypothesis: Residuals are homoskedastic (constant variance) Alternative hypothesis: Residuals are heteroskedastic

Decision Rule (5% Level)

If p-value > 0.05 → Fail to reject H₀ → No heteroskedasticity If p-value ≤ 0.05 → Reject H₀ → Heteroskedasticity exists

bp_test <- bptest(short_run_model)
bp_test
## 
##  studentized Breusch-Pagan test
## 
## data:  short_run_model
## BP = 7.8403, df = 7, p-value = 0.3469
7. Normality Test (Histogram / Jarque–Bera)

In small samples it is assumed that residuals are normally distributed. This validates t-tests and F-tests

Hypothesis Null Hypothesis: Residuals are normally distributed Alternative hypothesis: Residuals are not normally distributed

hist(residuals(short_run_model),
     main = "Histogram of Residuals",
     xlab = "Residuals",
     freq = FALSE)

lines(density(residuals(short_run_model)))

jarque.bera.test(residuals(short_run_model))
## 
##  Jarque Bera Test
## 
## data:  residuals(short_run_model)
## X-squared = 1.1453, df = 2, p-value = 0.564

Interpretation: There is no statistical evidence against the normality of the residuals.

Granger Causality Test

Granger causality does NOT mean true causation.

Granger Causality helps answering questions like Does Domestic Debt (DMDper) help predict GDP Growth (GDPGR)? Or does GDP growth help predict domestic debt?

Test 1: X - Y

Null Hypothesis: X does not Granger-cause Y Alternative Hypothesis: X Granger-causes Y

Test 2: Y - X

Null Hypothesis: Y does not Granger-cause X Alternative Hypothesis: Y Granger-causes X

Decision rule:

p-value < 0.05 → Reject H₀ p-value ≥ 0.05 → Fail to reject H₀

Testing Domestic debt to GDP Growth
granger_dmd_gdp <- grangertest(GDPGR ~ DMDper, order = 2, data = Main_Data_ts)
granger_gdp_dmd <- grangertest(DMDper ~ GDPGR, order = 2, data = Main_Data_ts)

granger_dmd_gdp
## Granger causality test
## 
## Model 1: GDPGR ~ Lags(GDPGR, 1:2) + Lags(DMDper, 1:2)
## Model 2: GDPGR ~ Lags(GDPGR, 1:2)
##   Res.Df Df      F Pr(>F)
## 1     18                 
## 2     20 -2 0.5386 0.5927
granger_gdp_dmd
## Granger causality test
## 
## Model 1: DMDper ~ Lags(DMDper, 1:2) + Lags(GDPGR, 1:2)
## Model 2: DMDper ~ Lags(DMDper, 1:2)
##   Res.Df Df      F Pr(>F)
## 1     18                 
## 2     20 -2 0.7167 0.5018

Interpretation: No causal relationship in either direction.

Testing Domestic debt servicing to GDP Growth
granger_dmds_gdp <- grangertest(GDPGR ~ DMDSERVper, order = 2, data = Main_Data_ts)
granger_gdp_dmds <- grangertest(DMDSERVper ~ GDPGR, order = 2, data = Main_Data_ts)

granger_dmds_gdp
## Granger causality test
## 
## Model 1: GDPGR ~ Lags(GDPGR, 1:2) + Lags(DMDSERVper, 1:2)
## Model 2: GDPGR ~ Lags(GDPGR, 1:2)
##   Res.Df Df      F Pr(>F)
## 1     18                 
## 2     20 -2 0.7722 0.4767
granger_gdp_dmds
## Granger causality test
## 
## Model 1: DMDSERVper ~ Lags(DMDSERVper, 1:2) + Lags(GDPGR, 1:2)
## Model 2: DMDSERVper ~ Lags(DMDSERVper, 1:2)
##   Res.Df Df      F Pr(>F)
## 1     18                 
## 2     20 -2 0.1514 0.8606
Testing Education to GDP Growth
granger_edu_gdp <- grangertest(GDPGR ~ EDUEXP, order = 2, data = Main_Data_ts)
granger_edu_gdp
## Granger causality test
## 
## Model 1: GDPGR ~ Lags(GDPGR, 1:2) + Lags(EDUEXP, 1:2)
## Model 2: GDPGR ~ Lags(GDPGR, 1:2)
##   Res.Df Df      F Pr(>F)
## 1     18                 
## 2     20 -2 2.0213 0.1615
Testing Health Expenditure to GDP Growth
granger_health_gdp <- grangertest(GDPGR ~ HLTHEXP, order = 2, data = Main_Data_ts)
granger_health_gdp
## Granger causality test
## 
## Model 1: GDPGR ~ Lags(GDPGR, 1:2) + Lags(HLTHEXP, 1:2)
## Model 2: GDPGR ~ Lags(GDPGR, 1:2)
##   Res.Df Df      F Pr(>F)
## 1     18                 
## 2     20 -2 0.2124 0.8106
Testing Inflation to GDP Growth
granger_inf_gdp <- grangertest(GDPGR ~ INF, order = 2, data = Main_Data_ts)
granger_inf_gdp
## Granger causality test
## 
## Model 1: GDPGR ~ Lags(GDPGR, 1:2) + Lags(INF, 1:2)
## Model 2: GDPGR ~ Lags(GDPGR, 1:2)
##   Res.Df Df      F  Pr(>F)  
## 1     18                    
## 2     20 -2 3.2285 0.06336 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Testing Interest Rate to GDP Growth
granger_int_gdp <- grangertest(GDPGR ~ INT, order = 2, data = Main_Data_ts)
granger_int_gdp
## Granger causality test
## 
## Model 1: GDPGR ~ Lags(GDPGR, 1:2) + Lags(INT, 1:2)
## Model 2: GDPGR ~ Lags(GDPGR, 1:2)
##   Res.Df Df      F Pr(>F)
## 1     18                 
## 2     20 -2 0.3027 0.7425