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).
The study aims to determine the impact of domestic debt and social spending on economic growth in Nigeria
What are the trends of domestic debt, social spending and economic growth in Nigeria?
What is the association between domestic debt, social spending and economic growth in Nigeria?
What is the direction of causality among domestic debt, social spending and economic growth in Nigeria?
Determine the trend of domestic debt, social spending and economic growth in Nigeria.
To examine the association between domestic debt, social spending and economic growth in Nigeria.
To evaluate the direction of causality among domestic debt, social spending and economic growth in Nigeria.
library(readr)
library(tidyverse)
#Load the data set
Main_Data <- read_csv("main_data.csv")
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
EDUEXP (Education Expenditure) Mean = 0.414, Median = 0.414 “The mean and median are almost identical, indicating symmetry.”
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).
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%).
DMDper (Domestic Debt): SD = 6.24 quite variable over years (from 1.17% to 25.36%).
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.
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")
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.
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:
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 <- 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
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
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.
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
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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
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 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₀
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.
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
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
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
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
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