5  Ordered Multinomial Models

# MEAN
formula_mean_v1 <- v1 ~ s_1 + s_2 + s_3 + s_4 + s_5 + s_6
formula_mean_v1_wo_ssa <- v1 ~ s_1 + s_2 + s_3 + s_4 + s_5 + s_6
formula_mean_v2 <- v2 ~ s_1 + s_2 + s_3 + s_4 + s_5 + s_6
formula_mean_v2_wo_ssa <- v2 ~ s_1 + s_2 + s_3 + s_4 + s_5 + s_6


# VARIANCE
formula_variance_v1 <- ~ s_1 + s_2 + s_4
formula_variance_v1_wo_ssa <- ~ s_1 + s_2 + s_4
formula_variance_v2 <- formula_variance_v2_wo_ssa <- ~ s_1 + s_2 + s_3 + s_4 

Rather than looking at the effects of socioeconomic variables on the cumulative number of cases, we look at the effects during the different phases of the incidence curve, i.e on the parameters that identify the severity of the ascending and declining phases of the crises (slow or rapid) and the dynamics of the disease in the early stage of a pandemic. Our two variables of interest are \(\hat{P}_i\) and \(\hat{\alpha}_i\), where the sub-index \(i\) refers to a country (we have a sample of 103 countries).

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.3     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(kableExtra)

Attaching package: 'kableExtra'

The following object is masked from 'package:dplyr':

    group_rows

Let us load the results obtained from the estimation of the generalized model:

load("./estim/resul_fit_countries.rda")

The coordinates obtained from the PCA:

load("./estim/results_pca/df_coordinates.rda")
estimates_nls <- 
  map(resul_fit_countries, "nls") |> 
  map_df("estimates", .id = "country") |> 
  mutate(estim = "nls")


df <- 
  estimates_nls |> 
  left_join(
    df_coordinates,
    by = "country"
  ) |> 
  rename(
    s_1 = coord_norm_s1,
    s_2 = coord_norm_s2,
    s_3 = coord_norm_s3,
    s_4 = coord_norm_s4,
    s_5 = coord_norm_s5,
    s_6 = coord_norm_s6
  )

For \(\hat{P}_i\) we define a three-level multidimensional ordered variable to characterize the dynamics during the initial phase of an epidemic: \[ {V}_{1i}= \begin{cases} 1, & \ \text{if} \ 0\leq \hat{P}_i \leq P_{.25}, \\ 2, & \ \text{if} \ P_{.25} < \hat{P}_i \leq P_{.75}, \\ 3, & \ \text{if} \ P_{.75} < \hat{P}_i \leq 1. \\ \end{cases} \tag{5.1}\] where \(P_{.25}\) and \(P_{.75}\) are chosen as the first and third quartiles of the observations of the vector \((\hat{P}_{i=1,...,100})\). The values 1,2,3 mean respectively “slow”, “medium” and “fast”.

For \(\hat{\alpha}_i\) we define a qualitative ordered variable with two characteristics: the speed of increase or decrease of an epidemic is either lower than the logistic decay (\(\hat{\alpha}_i \leq 1\)) or higher than the logistic decay (\(\hat{\alpha}_i > 1\)): \[ {V}_{2i}= \begin{cases} 1, & \ \text{if} \ \hat{\alpha}_i \leq 1, \\ 2, & \ \text{if} \ \hat{\alpha}_i > 1. \end{cases} \tag{5.2}\] where 1 means “lower” and 2 means “higher”.

Let us define those variables:

df <- 
  df |> 
  mutate(
    v2 = case_when(
      alpha <= 1 ~ 1,
      TRUE ~ 2
    ),
    v1 = case_when(
      P >= 0 & P <= quantile(P, probs = 0.25) ~ 1,
      P > quantile(P, probs = 0.25) & P <= quantile(P, probs = 0.75) ~ 2,
      P > quantile(P, probs = 0.75) & P <= 1 ~ 3,
      TRUE ~ 4
    )
  )

Sanity check:

table(df$v1)

 1  2  3 
29 57 29 
table(df$v2)

 1  2 
69 46 

We estimate ordered multinomial logit models, using the {oglmx} package. For each endogenous variable, we consider the following latent model: \[ V^*_{mi}= \sum_{k=1}^{6} \beta_k \ S_{ki} + \sigma_i \ \epsilon_{i}, \ \ \epsilon_{\kappa t} \approx N(0,1), \ m=1,2. \] The latent variable allows to define a partition of the endogenous variables as follows: \[ \hat{V}_{1i}= \begin{cases} 1, & \text{if} \ V_{1i}^* \in (-\infty,\lambda_1], \\ 2, & \text{if} \ V_{1i}^* \in (\lambda_1,\lambda_2] \\ 3, & \text{if} \ V_{1i}^* \in (\lambda_2,\infty). \end{cases} \tag{5.3}\] and \[ \hat{V}_{2i}= \begin{cases} 1, & \text{if} \ V_{2i}^* \in (-\infty,\gamma_1], \\ 2, & \text{if} \ V_{2i}^* \in (\gamma_1,\infty). \\ \end{cases} \tag{5.4}\]

The coefficient \(\lambda_1 >\lambda_2\) and \(\gamma_1\) are unknown parameters. Define \(S_i=(S_{1i},...,S_{6i})\) the vector of explanatory variables and \(\beta\) the vector of parameters to be estimated. The probability of an outcome conditional on the explanatory variables is: \[ Pr\left( \hat{V}_{mi} = \nu \ \lvert \ S_i, \ \beta \right)= \zeta \left( \kappa_{\nu+1}- S_{i}^{'} \ \beta \right) - \zeta \left( \kappa_{\nu} - S_{i}^{'} \ \beta \right). \] where \(\nu=1,2,3\) or \(\nu=1,2\) depending upon whether we consider the model (Equation 5.3) or (Equation 5.4). \(\kappa\) refers to the coefficients \(\lambda\) and \(\gamma\). \(\zeta(.)\) is the CDF of a logit model.\

5.1 Estimations

library(oglmx)

5.2 Impact on V1

Let us consider the estimation of the models that characterize the dynamics during the initial phase of the epidemic.

5.2.1 With all the Countries

In a first step, let us consider all the countries.

res_v1_o_prob <- oglmx(
  formulaMEAN = formula_mean_v1,
  formulaSD = formula_variance_v1,
  data = df,
  link = "probit", 
  constantMEAN = FALSE,
  constantSD = FALSE,
  delta = 0,
  threshparam = NULL
)

5.2.1.1 Summary

summary(res_v1_o_prob)
Heteroskedastic Ordered Probit Regression 
Log-Likelihood: -88.01135 
No. Iterations: 11 
McFadden's R2: 0.2660223 
AIC: 196.0227 
----- Mean Equation ------
    Estimate Std. error t value Pr(>|t|)  
s_1   5.4686     3.4844  1.5695  0.11654  
s_2   4.4385     3.6777  1.2069  0.22748  
s_3  -2.1331     1.5418 -1.3835  0.16650  
s_4   9.2440     6.9624  1.3277  0.18428  
s_5   3.0956     3.6597  0.8459  0.39763  
s_6  -4.9314     2.7665 -1.7825  0.07466 .
----- SD Equation ------
    Estimate Std. error t value  Pr(>|t|)    
s_2 -1.61034    1.51725 -1.0614    0.2885    
s_4  4.45907    0.99082  4.5004 6.783e-06 ***
----- Threshold Parameters -----
                 Estimate Std. error t value Pr(>|t|)
Threshold (1->2) -0.26948    3.93409 -0.0685   0.9454
Threshold (2->3)  5.78562    4.85658  1.1913   0.2335

5.2.1.2 Marginal Effects

Let us now compute the marginal effects, using the margins.oglmx() function from {oglmx}.

marginal_effects_v1 <- margins.oglmx(res_v1_o_prob, ascontinuous = TRUE)

Then, we can format the estimated values.

me_v1_table <- 
  map(marginal_effects_v1, as_tibble, rownames = "variable") |> 
  list_rbind(names_to = "state") |> 
  mutate(
    variable = factor(
      variable, 
      labels = c(
        "s_1" = "Healthcare infrastructure",
        "s_2" = "Vulnerability to comorbidites",
        "s_3" = "Vulnerability to natural environment",
        "s_4" = "Living conditions",
        "s_5" = "Economic and societal characteristics",
        "s_6" = "Policy variables and governance"
      )
    ),
    star = case_when(
      `Pr(>|t|)` < 0.01 ~ "***",
      `Pr(>|t|)` < 0.05 ~ "**",
      `Pr(>|t|)` < 0.1 ~ "*",
      TRUE ~ ""
    )
  ) |> 
  mutate(prob_state = str_c(round(`Marg. Eff`, 2), star)) |> 
  mutate(std_error = str_c("(", round(`Std. error`, 2), ")")) |> 
  select(variable, state, prob_state, std_error) |> 
  pivot_longer(c(prob_state, std_error)) |> 
  pivot_wider(names_from = state, values_from = value) |> 
  select(-name) |> 
  mutate(variable = as.character(variable)) |> 
  group_by(variable) |>
  mutate(variable = ifelse(row_number() == 1, variable, ""))

We can visualize the results as follows:

me_v1_table |> 
  mutate(
    `1` = kableExtra::cell_spec(
      `1`,
      color = case_when(
        str_detect(`1`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`1`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    ),
    `2` = kableExtra::cell_spec(
      `2`,
      color = case_when(
        str_detect(`2`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`2`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    ),
    `3` = kableExtra::cell_spec(
      `3`,
      color = case_when(
        str_detect(`3`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`3`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    )
  ) |> 
  ungroup() |> 
  knitr::kable(
    escape = F, booktabs = T, format = "html",
    caption = str_c(
      "Marginal effects of the synthetic variables ",
      "on the probability of being in each regime for V1"
    ),
    col.names = c(
      "Variable", "\\(\\mathbb{P}(V_1 = 1)\\)<br>(Slow Start)", 
      "\\(\\mathbb{P}(V_1 = 2)\\)<br>(Medium Start)",
      "\\(\\mathbb{P}(V_1 = 3)\\)<br>(Fast Start)"
    )
  ) |>
  kableExtra::add_header_above(c(" ", "Marginal effect on:" = 3)) |> 
  kableExtra::kable_styling()
Marginal effects of the synthetic variables on the probability of being in each regime for V1
Marginal effect on:
Variable \(\mathbb{P}(V_1 = 1)\)
(Slow Start)
\(\mathbb{P}(V_1 = 2)\)
(Medium Start)
\(\mathbb{P}(V_1 = 3)\)
(Fast Start)
Healthcare infrastructure -0.36** -0.05 0.41*
(0.17) (0.1) (0.23)
Vulnerability to comorbidites -0.66 0.64 0.02
(0.46) (0.64) (0.32)
Living conditions 0.42 -1.99*** 1.57***
(0.39) (0.52) (0.47)
Vulnerability to natural environment 0.14 0.02 -0.16
(0.1) (0.04) (0.11)
Economic and societal characteristics -0.2 -0.03 0.23
(0.23) (0.06) (0.26)
Policy variables and governance 0.33* 0.05 -0.37*
(0.18) (0.08) (0.21)

5.2.2 Without Sub-Saharan Africa

Let us reestimate the same model, but without Sub-Saharan Africa.

results_o_prob_wo_ssa <- oglmx(
  formulaMEAN = formula_mean_v1_wo_ssa,
  formulaSD = formula_variance_v1_wo_ssa,
  data = df |> filter(!group %in% "Sub-Saharan Africa"),
  link = "probit", 
  constantMEAN = FALSE,
  constantSD = FALSE,
  delta = 0,
  threshparam = NULL
)

5.2.2.1 Summary

summary(results_o_prob_wo_ssa)
Heteroskedastic Ordered Probit Regression 
Log-Likelihood: -47.34021 
No. Iterations: 11 
McFadden's R2: 0.220331 
AIC: 114.6804 
----- Mean Equation ------
    Estimate Std. error t value Pr(>|t|)
s_1   4.8333     4.2913  1.1263   0.2600
s_2   5.4116     6.5549  0.8256   0.4090
s_3  -1.7482     1.7799 -0.9822   0.3260
s_4   6.8768     7.2773  0.9450   0.3447
s_5   3.8568     3.8467  1.0026   0.3160
s_6  -5.0477     3.1967 -1.5790   0.1143
----- SD Equation ------
    Estimate Std. error t value Pr(>|t|)
s_2   1.3705     2.2431  0.6110   0.5412
s_4   2.4486     1.6835  1.4544   0.1458
----- Threshold Parameters -----
                 Estimate Std. error t value Pr(>|t|)
Threshold (1->2) -0.20451    4.24128 -0.0482   0.9615
Threshold (2->3)  5.99920    5.44750  1.1013   0.2708

5.2.2.2 Marginal Effects

marginal_effects_v1_wo_ssa <- margins.oglmx(
  results_o_prob_wo_ssa, 
  ascontinuous = TRUE
)

Let us format the results.

me_v1_wo_ssa_table <- 
  map(marginal_effects_v1_wo_ssa, as_tibble, rownames = "variable") |> 
  list_rbind(names_to = "state") |> 
  mutate(
    variable = factor(
      variable, 
      labels = c(
        "s_1" = "Healthcare infrastructure",
        "s_2" = "Vulnerability to comorbidites",
        "s_3" = "Vulnerability to natural environment",
        "s_4" = "Living conditions",
        "s_5" = "Economic and societal characteristics",
        "s_6" = "Policy variables and governance"
      )
    ),
    star = case_when(
      `Pr(>|t|)` < 0.01 ~ "***",
      `Pr(>|t|)` < 0.05 ~ "**",
      `Pr(>|t|)` < 0.1 ~ "*",
      TRUE ~ ""
    )
  ) |> 
  mutate(prob_state = str_c(round(`Marg. Eff`, 2), star)) |> 
  mutate(std_error = str_c("(", round(`Std. error`, 2), ")")) |> 
  select(variable, state, prob_state, std_error) |> 
  pivot_longer(c(prob_state, std_error)) |> 
  pivot_wider(names_from = state, values_from = value) |> 
  select(-name) |> 
  mutate(variable = as.character(variable)) |> 
  group_by(variable) |>
  mutate(variable = ifelse(row_number() == 1, variable, ""))

They can then be displayed:

me_v1_wo_ssa_table |> 
  mutate(
    `1` = kableExtra::cell_spec(
      `1`,
      color = case_when(
        str_detect(`1`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`1`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    ),
    `2` = kableExtra::cell_spec(
      `2`,
      color = case_when(
        str_detect(`2`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`2`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    ),
    `3` = kableExtra::cell_spec(
      `3`,
      color = case_when(
        str_detect(`3`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`3`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    )
  ) |> 
  ungroup() |> 
  knitr::kable(
    escape = F, booktabs = T, format = "html",
    caption = str_c(
      "Marginal effects of the synthetic variables ",
      "on the probability of being in each regime for V1, ",
      "without Sub-Saharan Africa"
    ),
    col.names = c(
      "Variable", "\\(\\mathbb{P}(V_1 = 1)\\)<br>(Slow Start)", 
      "\\(\\mathbb{P}(V_1 = 2)\\)<br>(Medium Start)",
      "\\(\\mathbb{P}(V_1 = 3)\\)<br>(Fast Start)"
    )
  ) |>
  kableExtra::add_header_above(c(" ", "Marginal effect on:" = 3)) |> 
  kableExtra::kable_styling()
Marginal effects of the synthetic variables on the probability of being in each regime for V1, without Sub-Saharan Africa
Marginal effect on:
Variable \(\mathbb{P}(V_1 = 1)\)
(Slow Start)
\(\mathbb{P}(V_1 = 2)\)
(Medium Start)
\(\mathbb{P}(V_1 = 3)\)
(Fast Start)
Healthcare infrastructure -0.54 0.33 0.2
(0.37) (0.27) (0.17)
Vulnerability to comorbidites -0.27 -0.19 0.46
(0.87) (1.09) (0.52)
Living conditions -0.18 -0.53 0.71*
(0.84) (0.91) (0.42)
Vulnerability to natural environment 0.19 -0.12 -0.07
(0.19) (0.12) (0.08)
Economic and societal characteristics -0.43 0.26 0.16
(0.4) (0.28) (0.16)
Policy variables and governance 0.56* -0.35 -0.21
(0.34) (0.26) (0.15)

5.2.3 Reproduction of Table 2

me_v1_both <- 
  map(marginal_effects_v1, as_tibble, rownames = "variable") |> 
  list_rbind(names_to = "state") |> 
  mutate(model = "All") |> 
  bind_rows(
    map(marginal_effects_v1_wo_ssa, as_tibble, rownames = "variable") |> 
      list_rbind(names_to = "state") |> 
      mutate(model = "Without SSA")
  ) |> 
  mutate(
    variable = factor(
      variable, 
      labels = c(
        "s_1" = "Healthcare infrastructure",
        "s_2" = "Vulnerability to comorbidites",
        "s_3" = "Vulnerability to natural environment",
        "s_4" = "Living conditions",
        "s_5" = "Economic and societal characteristics",
        "s_6" = "Policy variables and governance"
      )
    ),
    star = case_when(
      `Pr(>|t|)` < 0.01 ~ "***",
      `Pr(>|t|)` < 0.05 ~ "**",
      `Pr(>|t|)` < 0.1 ~ "*",
      TRUE ~ ""
    )
  ) |> 
  mutate(prob_state = str_c(round(`Marg. Eff`, 2), star)) |> 
  mutate(std_error = str_c("(", round(`Std. error`, 2), ")")) |> 
  select(model, variable, state, prob_state, std_error) |> 
  pivot_longer(c(prob_state, std_error)) |> 
  pivot_wider(names_from = c(model, state), values_from = value) |> 
  select(-name) |> 
  mutate(variable = as.character(variable)) |> 
  group_by(variable) |>
  mutate(variable = ifelse(row_number() == 1, variable, ""))
me_v1_both |> 
  mutate(
    across(
      All_1:`Without SSA_3`, 
      ~kableExtra::cell_spec(
        .x,
        color = case_when(
          str_detect(.x, "^\\(|-", negate = TRUE) ~ "#009D57",
          str_detect(.x, "^-") ~ "#EE324E",
          TRUE ~ "black"
        )
      )
    )
  ) |> 
  ungroup() |> 
  knitr::kable(
    escape = F, booktabs = T, format = "html",
    caption = str_c(
      "Marginal effects of the synthetic variables ",
      "on the probability of being in each regime for V1"
    ),
    col.names = c(
      "Variable",
      rep(
        c(
          "\\(\\mathbb{P}(V_1 = 1)\\)<br>(Slow Start)", 
          "\\(\\mathbb{P}(V_1 = 2)\\)<br>(Medium Start)",
          "\\(\\mathbb{P}(V_1 = 3)\\)<br>(Fast Start)"
        ),
        2
      )
    )
  ) |>
  kableExtra::add_header_above(
    c(" ", "All countries" = 3, "Without Sub-Saharan Africa" = 3)
  ) |> 
  kableExtra::kable_styling()
Marginal effects of the synthetic variables on the probability of being in each regime for V1
All countries
Without Sub-Saharan Africa
Variable \(\mathbb{P}(V_1 = 1)\)
(Slow Start)
\(\mathbb{P}(V_1 = 2)\)
(Medium Start)
\(\mathbb{P}(V_1 = 3)\)
(Fast Start)
\(\mathbb{P}(V_1 = 1)\)
(Slow Start)
\(\mathbb{P}(V_1 = 2)\)
(Medium Start)
\(\mathbb{P}(V_1 = 3)\)
(Fast Start)
Healthcare infrastructure -0.36** -0.05 0.41* -0.54 0.33 0.2
(0.17) (0.1) (0.23) (0.37) (0.27) (0.17)
Vulnerability to comorbidites -0.66 0.64 0.02 -0.27 -0.19 0.46
(0.46) (0.64) (0.32) (0.87) (1.09) (0.52)
Living conditions 0.42 -1.99*** 1.57*** -0.18 -0.53 0.71*
(0.39) (0.52) (0.47) (0.84) (0.91) (0.42)
Vulnerability to natural environment 0.14 0.02 -0.16 0.19 -0.12 -0.07
(0.1) (0.04) (0.11) (0.19) (0.12) (0.08)
Economic and societal characteristics -0.2 -0.03 0.23 -0.43 0.26 0.16
(0.23) (0.06) (0.26) (0.4) (0.28) (0.16)
Policy variables and governance 0.33* 0.05 -0.37* 0.56* -0.35 -0.21
(0.18) (0.08) (0.21) (0.34) (0.26) (0.15)

5.3 Impact on V2

Let us now turn to the estimation of \(V_2\).

5.3.1 With all the Countries

results_o_prob_v2 <- oglmx(
  formulaMEAN = formula_mean_v2,
  formulaSD = formula_variance_v2,
  data = df,
  link = "probit", 
  constantMEAN = FALSE,
  constantSD = FALSE,
  delta = 0,
  threshparam = NULL
)

5.3.1.1 Summary

summary(results_o_prob_v2)
Heteroskedastic Probit Regression 
Log-Likelihood: -65.90037 
No. Iterations: 17 
McFadden's R2: 0.1485338 
AIC: 151.8007 
----- Mean Equation ------
     Estimate Std. error t value Pr(>|t|)
s_1 -1.112638   1.167421 -0.9531   0.3406
s_2 -1.715519   1.763663 -0.9727   0.3307
s_3  0.644278   0.616647  1.0448   0.2961
s_4  1.713390   1.821409  0.9407   0.3469
s_5  0.835133   1.248853  0.6687   0.5037
s_6  0.072766   0.439697  0.1655   0.8686
----- SD Equation ------
    Estimate Std. error t value Pr(>|t|)  
s_2  5.27218    3.80034  1.3873  0.16535  
s_3 -0.19134    1.25145 -0.1529  0.87848  
s_4 -3.43431    2.02201 -1.6985  0.08942 .
----- Threshold Parameters -----
                 Estimate Std. error t value Pr(>|t|)
Threshold (1->2)   1.2329     1.5020  0.8208   0.4118

5.3.1.2 Marginal Effects

marginal_effects_v2 <- margins.oglmx(results_o_prob_v2, ascontinuous = TRUE)
me_v2_table <- 
  map(marginal_effects_v2, as_tibble, rownames = "variable") |> 
  list_rbind(names_to = "state") |> 
  mutate(
    variable = factor(
      variable, 
      labels = c(
        "s_1" = "Healthcare infrastructure",
        "s_2" = "Vulnerability to comorbidites",
        "s_3" = "Vulnerability to natural environment",
        "s_4" = "Living conditions",
        "s_5" = "Economic and societal characteristics",
        "s_6" = "Policy variables and governance"
      )
    ),
    star = case_when(
      `Pr(>|t|)` < 0.01 ~ "***",
      `Pr(>|t|)` < 0.05 ~ "**",
      `Pr(>|t|)` < 0.1 ~ "*",
      TRUE ~ ""
    )
  ) |> 
  mutate(prob_state = str_c(round(`Marg. Eff`, 2), star)) |> 
  mutate(std_error = str_c("(", round(`Std. error`, 2), ")")) |> 
  select(variable, state, prob_state, std_error) |> 
  pivot_longer(c(prob_state, std_error)) |> 
  pivot_wider(names_from = state, values_from = value) |> 
  select(-name) |> 
  mutate(variable = as.character(variable)) |> 
  group_by(variable) |>
  mutate(variable = ifelse(row_number() == 1, variable, ""))
me_v2_table |> 
  mutate(
    `1` = kableExtra::cell_spec(
      `1`,
      color = case_when(
        str_detect(`1`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`1`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    ),
    `2` = kableExtra::cell_spec(
      `2`,
      color = case_when(
        str_detect(`2`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`2`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    )
  ) |> 
  ungroup() |> 
  knitr::kable(
    escape = F, booktabs = T, format = "html",
    caption = str_c(
      "Marginal effects of the synthetic variables ",
      "on the probability of being in each regime for V2"
    ),
    col.names = c(
      "Variable", "\\(\\mathbb{P}(V_2 = 1)\\)<br>(Speed slower than the logistic decay)", 
      "\\(\\mathbb{P}(V_2 = 2)\\)<br>(Speed faster than the logistic decay)"
    )
  ) |>
  kableExtra::add_header_above(c(" ", "Marginal effect on:" = 2)) |> 
  kableExtra::kable_styling()
Marginal effects of the synthetic variables on the probability of being in each regime for V2
Marginal effect on:
Variable \(\mathbb{P}(V_2 = 1)\)
(Speed slower than the logistic decay)
\(\mathbb{P}(V_2 = 2)\)
(Speed faster than the logistic decay)
Healthcare infrastructure 0.5 -0.5
(0.6) (0.6)
Vulnerability to comorbidites -0.13 0.13
(0.93) (0.93)
Vulnerability to natural environment -0.26 0.26
(0.29) (0.29)
Living conditions -0.18 0.18
(0.65) (0.65)
Economic and societal characteristics -0.37 0.37
(0.39) (0.39)
Policy variables and governance -0.03 0.03
(0.19) (0.19)

5.3.2 Without Sub-Saharan Africa

results_o_prob_v2_wo_ssa <- oglmx(
  formulaMEAN = formula_mean_v2_wo_ssa,
  formulaSD = formula_variance_v2_wo_ssa,
  data = df |> filter(!group %in% "Sub-Saharan Africa"),
  link = "probit", 
  constantMEAN = FALSE,
  constantSD = FALSE,
  delta = 0,
  threshparam = NULL
)

5.3.2.1 Summary

All the models in a single object.

summary(results_o_prob_v2_wo_ssa)
Heteroskedastic Probit Regression 
Log-Likelihood: -35.63926 
No. Iterations: 13 
McFadden's R2: 0.1685392 
AIC: 91.27851 
----- Mean Equation ------
    Estimate Std. error t value Pr(>|t|)
s_1 -2.77647    2.21493 -1.2535   0.2100
s_2 -0.94394    1.09380 -0.8630   0.3881
s_3  0.51990    0.34860  1.4914   0.1359
s_4 -1.05977    1.30355 -0.8130   0.4162
s_5  0.28903    0.51412  0.5622   0.5740
s_6 -0.75580    0.58748 -1.2865   0.1983
----- SD Equation ------
    Estimate Std. error t value Pr(>|t|)  
s_2  -5.1107     7.3024 -0.6999  0.48401  
s_3  -2.9968     1.3833 -2.1664  0.03028 *
s_4   3.7335     6.6236  0.5637  0.57298  
----- Threshold Parameters -----
                 Estimate Std. error t value Pr(>|t|)
Threshold (1->2) -0.88751    0.79300 -1.1192   0.2631

5.3.2.2 Marginal Effects

Again, we use the margins.oglmx() function to compute the marginal effects.

marginal_effects_v2_wo_ssa <- margins.oglmx(
  results_o_prob_v2_wo_ssa, 
  ascontinuous = TRUE
)
me_v2_wo_ssa_table <- 
  map(marginal_effects_v2_wo_ssa, as_tibble, rownames = "variable") |> 
  list_rbind(names_to = "state") |> 
  mutate(
    variable = factor(
      variable, 
      labels = c(
        "s_1" = "Healthcare infrastructure",
        "s_2" = "Vulnerability to comorbidites",
        "s_3" = "Vulnerability to natural environment",
        "s_4" = "Living conditions",
        "s_5" = "Economic and societal characteristics",
        "s_6" = "Policy variables and governance"
      )
    ),
    star = case_when(
      `Pr(>|t|)` < 0.01 ~ "***",
      `Pr(>|t|)` < 0.05 ~ "**",
      `Pr(>|t|)` < 0.1 ~ "*",
      TRUE ~ ""
    )
  ) |> 
  mutate(prob_state = str_c(round(`Marg. Eff`, 2), star)) |> 
  mutate(std_error = str_c("(", round(`Std. error`, 2), ")")) |> 
  select(variable, state, prob_state, std_error) |> 
  pivot_longer(c(prob_state, std_error)) |> 
  pivot_wider(names_from = state, values_from = value) |> 
  select(-name) |> 
  mutate(variable = as.character(variable)) |> 
  group_by(variable) |>
  mutate(variable = ifelse(row_number() == 1, variable, ""))

Then, we can print the results.

me_v2_wo_ssa_table |> 
  mutate(
    `1` = kableExtra::cell_spec(
      `1`,
      color = case_when(
        str_detect(`1`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`1`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    ),
    `2` = kableExtra::cell_spec(
      `2`,
      color = case_when(
        str_detect(`2`, "^\\(|-", negate = TRUE) ~ "#009D57",
        str_detect(`2`, "^-") ~ "#EE324E",
        TRUE ~ "black"
      )
    )
  ) |> 
  ungroup() |> 
  knitr::kable(
    escape = F, booktabs = T, format = "html",
    caption = str_c(
      "Marginal effects of the synthetic variables ",
      "on the probability of being in each regime for V2, ",
      "without Sub-Saharan Africa"
    ),
    col.names = c(
      "Variable", "\\(\\mathbb{P}(V_2 = 1)\\)<br>(Speed slower than the logistic decay)", 
      "\\(\\mathbb{P}(V_2 = 2)\\)<br>(Speed faster than the logistic decay)"
    )
  ) |>
  kableExtra::add_header_above(c(" ", "Marginal effect on:" = 2)) |> 
  kableExtra::kable_styling()
Marginal effects of the synthetic variables on the probability of being in each regime for V2, without Sub-Saharan Africa
Marginal effect on:
Variable \(\mathbb{P}(V_2 = 1)\)
(Speed slower than the logistic decay)
\(\mathbb{P}(V_2 = 2)\)
(Speed faster than the logistic decay)
Healthcare infrastructure 1.46*** -1.46***
(0.45) (0.45)
Vulnerability to comorbidites 1.71 -1.71
(2.26) (2.26)
Vulnerability to natural environment 0.44 -0.44
(0.31) (0.31)
Living conditions -0.33 0.33
(1.89) (1.89)
Economic and societal characteristics -0.15 0.15
(0.22) (0.22)
Policy variables and governance 0.4** -0.4**
(0.19) (0.19)

5.3.3 Reproduction of Table 3

me_v2_both <- 
  map(marginal_effects_v2, as_tibble, rownames = "variable") |> 
  list_rbind(names_to = "state") |> 
  mutate(model = "All") |> 
  bind_rows(
    map(marginal_effects_v2_wo_ssa, as_tibble, rownames = "variable") |> 
      list_rbind(names_to = "state") |> 
      mutate(model = "Without SSA")
  ) |> 
  mutate(
    variable = factor(
      variable, 
      labels = c(
        "s_1" = "Healthcare infrastructure",
        "s_2" = "Vulnerability to comorbidites",
        "s_3" = "Vulnerability to natural environment",
        "s_4" = "Living conditions",
        "s_5" = "Economic and societal characteristics",
        "s_6" = "Policy variables and governance"
      )
    ),
    star = case_when(
      `Pr(>|t|)` < 0.01 ~ "***",
      `Pr(>|t|)` < 0.05 ~ "**",
      `Pr(>|t|)` < 0.1 ~ "*",
      TRUE ~ ""
    )
  ) |> 
  mutate(prob_state = str_c(round(`Marg. Eff`, 2), star)) |> 
  mutate(std_error = str_c("(", round(`Std. error`, 2), ")")) |> 
  select(model, variable, state, prob_state, std_error) |> 
  pivot_longer(c(prob_state, std_error)) |> 
  pivot_wider(names_from = c(model, state), values_from = value) |> 
  select(-name) |> 
  mutate(variable = as.character(variable)) |> 
  group_by(variable) |>
  mutate(variable = ifelse(row_number() == 1, variable, ""))
me_v2_both |> 
  mutate(
    across(
      All_1:`Without SSA_2`, 
      ~kableExtra::cell_spec(
        .x,
        color = case_when(
          str_detect(.x, "^\\(|-", negate = TRUE) ~ "#009D57",
          str_detect(.x, "^-") ~ "#EE324E",
          TRUE ~ "black"
        )
      )
    )
  ) |> 
  ungroup() |> 
  knitr::kable(
    escape = FALSE, booktabs = T, format = "html",
    caption = str_c(
      "Marginal effects of the synthetic variables ",
      "on the probability of being in each regime for V2"
    ),
    col.names = c(
      "Variable",
      rep(
        c(
          "\\(\\mathbb{P}(V_2 = 1)\\)<br>(Slower)", 
          "\\(\\mathbb{P}(V_2 = 2)\\)<br>(Faster)"
        ),
        2
      )
    )
  ) |>
  kableExtra::add_header_above(
    c(" ", "All countries" = 2, "Without Sub-Saharan Africa" = 2)
  ) |> 
  kableExtra::kable_styling()
Marginal effects of the synthetic variables on the probability of being in each regime for V2
All countries
Without Sub-Saharan Africa
Variable \(\mathbb{P}(V_2 = 1)\)
(Slower)
\(\mathbb{P}(V_2 = 2)\)
(Faster)
\(\mathbb{P}(V_2 = 1)\)
(Slower)
\(\mathbb{P}(V_2 = 2)\)
(Faster)
Healthcare infrastructure 0.5 -0.5 1.46*** -1.46***
(0.6) (0.6) (0.45) (0.45)
Vulnerability to comorbidites -0.13 0.13 1.71 -1.71
(0.93) (0.93) (2.26) (2.26)
Vulnerability to natural environment -0.26 0.26 0.44 -0.44
(0.29) (0.29) (0.31) (0.31)
Living conditions -0.18 0.18 -0.33 0.33
(0.65) (0.65) (1.89) (1.89)
Economic and societal characteristics -0.37 0.37 -0.15 0.15
(0.39) (0.39) (0.22) (0.22)
Policy variables and governance -0.03 0.03 0.4** -0.4**
(0.19) (0.19) (0.19) (0.19)