AI x Blended learning

Preparation

Importing packages and data

Show the code
library(dplyr)
library(metafor)
library(tidyr)
library(Hmisc)
library(emmeans)
options(scipen = 9999999)
col.contour = c("gray75", "gray85", "gray95")

data <- rio::import("AI_Blended.xlsx") |> 
  select(-3,-9,-10) 

Calculating effect sizes

Show the code
# Assume a correlation of 0.7 between pre-test and post-test scores
r <- 0.7

# Modify the data transformation with the correlation
datah <- data |> rowwise() |>
  mutate(
    # Mean differences for experimental and control groups
    MD_exp = MEpost - ifelse(is.na(MEpre),0,MEpre),   
    MD_con = MCpost - ifelse(is.na(MCpre),0,MCpre),   
    
    # Pooled SD considering the correlation between pre and post
    SD_pooled_exp = ifelse(is.na(SDEpre), SDEpost, sqrt(SDEpre^2 + SDEpost^2 - 2 * r * SDEpre * SDEpost)),  # For experimental group
    SD_pooled_con = ifelse(is.na(SDCpre), SDCpost, sqrt(SDCpre^2 + SDCpost^2 - 2 * r * SDCpre * SDCpost)),  # For control group
    
    # Hedge's g calculation considering the correlation
    SD_pooled = sqrt(((NC - 1) * SD_pooled_con^2 + (NE - 1) * SD_pooled_exp^2) / (NC + NE - 2)), 
    g = (MD_exp - MD_con) / SD_pooled,   # Hedge's g without correction
    J = 1 - (3 / (4 * (NC + NE) - 9)),   # Correction factor for small sample sizes
    Hedge_g = g * J  # Apply correction factor
  )

# Now you can use escalc() to calculate variance and other stats
results <- escalc(
  measure = "SMD", 
  yi = Hedge_g, 
  vi = (1/NC + 1/NE) + Hedge_g^2 / (2*(NC + NE)), 
  data = datah
) |> data.frame()


# Comment this to NOT flip the ES of the only post papers
results |> mutate(
  Hedge_g = ifelse(is.na(MCpre), -Hedge_g, Hedge_g),
  yi = ifelse(is.na(MCpre), -yi, yi)
) -> results

Meta-analysis

Estimation

Show the code
m.gen <- meta::metagen(TE = Hedge_g, 
                       seTE = vi^.5,
                       studlab = `X.`,
                       data = results,
                       fixed = FALSE,
                       random = TRUE,
                       method.tau = "REML",
                       hakn = T)

Plotting

Show the code
meta:::forest.meta(m.gen, 
              layout = "meta",
              sortvar = -g,
              digits = 3,
              print.tau2 = TRUE,
              prediction = TRUE,
              leftlabs = c("Study"),
              xlim = c(-2,2),
              leftcols = c("Author..year."),
              col.square = "orange",
              col.diamond = "red",
              plotwidth = "5cm",
              colgap.forest.left = "5cm")

Bias

Show the code
m_multi = metafor::rma(results$Hedge_g,results$vi, 
                          data = results, slab = results$Author..year.)
meta:::funnel.meta(m.gen, xlim = c(-2, 4.5), contour = c(0.9, 0.95, 0.99), col.contour = col.contour)

Show the code
metafor::ranktest(m_multi)

Rank Correlation Test for Funnel Plot Asymmetry

Kendall's tau = 0.4381, p = 0.0050
Show the code
metafor::regtest(m_multi)

Regression Test for Funnel Plot Asymmetry

Model:     mixed-effects meta-regression model
Predictor: standard error

Test for Funnel Plot Asymmetry: z =  3.1906, p = 0.0014
Limit Estimate (as sei -> 0):   b = -0.1209 (CI: -0.5676, 0.3258)

Outliers (https://bookdown.org/MathiasHarrer/Doing_Meta_Analysis_in_R/heterogeneity.html?q=OUTLIERS#basic-outlier)

Show the code
outliers <- dmetar::find.outliers(m.gen)
m.gen.inf <- dmetar::InfluenceAnalysis(m.gen, random = TRUE)
[===========================================================================] DONE 
Show the code
ggplot2::theme_set(ggplot2::theme_minimal())
plot(m.gen.inf, "baujat") 

Show the code
plot(m.gen.inf, "es")

Show the code
plot(m.gen.inf, "i2")

Remove outliers

Show the code
results2 <- results |> filter(!(X. %in% outliers$out.study.random))

Re-estimate without outliers

Show the code
m.gen2 <- meta::metagen(TE = Hedge_g, 
                       seTE = vi^.5,
                       studlab = `X.`,
                       data = results2,
                       fixed = FALSE,
                       random = TRUE,
                       method.tau = "REML",
                       hakn = T)

Plotting

Show the code
meta:::forest.meta(m.gen2, 
              layout = "meta",
              sortvar = -g,
              digits = 3,
              print.tau2 = TRUE,
              prediction = TRUE,
              leftlabs = c("Study"),
              xlim = c(-2,2),
              leftcols = c("Author..year."),
              plotwidth = "5cm",
              colgap.forest.left = "5cm")

Bias after removing outliers

Show the code
m_multi2 = metafor::rma(results2$Hedge_g,results2$vi, 
                          data = results2, slab = results2$Author..year.)
meta:::funnel.meta(m.gen2, xlim = c(-2, 4.5), contour = c(0.9, 0.95, 0.99), col.contour = col.contour)

Show the code
metafor::ranktest(m_multi2)

Rank Correlation Test for Funnel Plot Asymmetry

Kendall's tau = 0.4000, p = 0.0326
Show the code
metafor::regtest(m_multi2)

Regression Test for Funnel Plot Asymmetry

Model:     mixed-effects meta-regression model
Predictor: standard error

Test for Funnel Plot Asymmetry: z = 2.0942, p = 0.0362
Limit Estimate (as sei -> 0):   b = 0.0021 (CI: -0.3700, 0.3743)

Subgroup analysis

Show the code
subgroup.results <- function(current_meta, pretty = T) {
 subgroup_df <- data.frame(
    Subgroup = current_meta$bylevs,
    k = current_meta$k.w,
    g = current_meta$TE.random.w,
    SE = current_meta$seTE.random.w,
    CI_Lower = current_meta$lower.random.w,
    CI_Upper = current_meta$upper.random.w,
    p =  current_meta$pval.random.w,
    Tau =  current_meta$tau.w,
    Tau2 =  current_meta$tau2.w
  ) |> 
    mutate(
      stars = case_when(
              p <= 0.001 ~ "***",
              p <= 0.01 ~ "**",
              p <= 0.05 ~ "*",
              TRUE ~ ""
            )
    ) |>
    mutate_if(is.numeric, \(x) format(x, digits = 2)) |>
    mutate(
      `95%-CI` = paste0("[",CI_Lower,"; ",CI_Upper,"]"),
    ) |>
    mutate_if(is.character, \(x) ifelse(is.na(x), "", x)) |>
   select(Subgroup, k, g, SE, `95%-CI`, p, stars, Tau2, Tau)
  
  if (isTRUE(pretty)) {
    gt::gt(subgroup_df) |> 
      gt::fmt_number(decimals = 2) |> 
      gt::sub_missing(
      columns = everything(),
      rows = everything(),
      missing_text = "_"
    )
  } else {
    subgroup_df
  }
}

By AI technology

Show the code
m.genAI <- meta::metagen(TE = Hedge_g, 
                       seTE = vi^.5,
                       studlab = `Author..year.`,
                       data = results,
                       sm = "SMD",
                       fixed = FALSE,
                       random = TRUE,
                       subgroup = results$AI,
                       cluster = results$`X.`,
                       method.tau = "REML",
                       hakn = TRUE)

meta:::forest.meta(m.genAI, 
              layout = "meta",
              sortvar = g,
              print.tau2 = TRUE,
              prediction = TRUE,
              leftlabs = c("Study"),
              xlim = c(-2,2),
              subgroup.name = "AI technology",
               col.square = "orange",
                       plotwidth = "5.5cm",
                       col.diamond = "red",
              leftcols = c("studlab"),
              colgap.forest.left = "5cm")

m.genAI
Number of studies: k = 21

                             SMD           95%-CI    t p-value
Random effects model (HK) 0.5310 [0.2658; 0.7961] 4.18  0.0005

Quantifying heterogeneity:
 tau^2 = 0.2159 [0.1305; 0.9291]; tau = 0.4647 [0.3612; 0.9639]
 I^2 = 87.0% [81.5%; 90.9%]; H = 2.77 [2.32; 3.31]

Test of heterogeneity:
      Q d.f.  p-value
 153.86   20 < 0.0001

Results for subgroups (random effects model (HK)):
                    k    SMD            95%-CI  tau^2    tau      Q   I^2
AI = ITS           16 0.4635 [ 0.1314; 0.7957] 0.2308 0.4804 129.41 88.4%
AI = Personalized   4 0.8764 [ 0.2612; 1.4916] 0.0938 0.3062   7.54 60.2%
AI = Chatbot        1 0.3382 [-0.1714; 0.8479]     --     --   0.00    --

Test for subgroup differences (random effects model (HK)):
                  Q d.f. p-value
Between groups 3.77    2  0.1517

Details on meta-analytical method:
- Inverse variance method
- Restricted maximum-likelihood estimator for tau^2
- Q-Profile method for confidence interval of tau^2 and tau
- Hartung-Knapp adjustment for random effects model (df = 20)

Figure 1: Subgroup by AI technology

Show the code
res2 = metafor::rma(results$Hedge_g,results$vi,  method="REML", mods= ~ `AI`, data = results)
Binded = cbind(res2$m, res2$QM, res2$QMp, res2$QE, res2$QEp )
colnames(Binded)= c( "DF", "QM", "P", "QE", "P")
res2

Mixed-Effects Model (k = 21; tau^2 estimator: REML)

tau^2 (estimated amount of residual heterogeneity):     0.2068 (SE = 0.0854)
tau (square root of estimated tau^2 value):             0.4547
I^2 (residual heterogeneity / unaccounted variability): 87.48%
H^2 (unaccounted variability / sampling variability):   7.99
R^2 (amount of heterogeneity accounted for):            4.23%

Test for Residual Heterogeneity:
QE(df = 18) = 136.9433, p-val < .0001

Test of Moderators (coefficients 2:3):
QM(df = 2) = 2.1751, p-val = 0.3370

Model Results:

                estimate      se    zval    pval    ci.lb   ci.ub    
intrcpt           0.3382  0.5238  0.6457  0.5185  -0.6884  1.3649    
AIITS             0.1206  0.5391  0.2236  0.8230  -0.9361  1.1772    
AIPersonalized    0.5354  0.5854  0.9146  0.3604  -0.6120  1.6828    

---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
Binded 
     DF       QM         P       QE                            P
[1,]  2 2.175068 0.3370466 136.9433 0.00000000000000000002481715
Show the code
subgroup.results(m.genAI)
Subgroup k g SE 95%-CI p stars Tau2 Tau
ITS 16 0.46 0.16 [ 0.13; 0.80] 0.0095 ** 0.231 0.48
Personalized 4 0.88 0.19 [ 0.26; 1.49] 0.0201 * 0.094 0.31
Chatbot 1 0.34 0.26 [-0.17; 0.85] 0.1933 NA NA

By research design

Show the code
m.genRD <- meta::metagen(TE = Hedge_g, 
                       seTE = vi^.5,
                       studlab = `Author..year.`,
                       data = results,
                       sm = "SMD",
                       fixed = FALSE,
                       random = TRUE,
                       subgroup = results$Research.Design,
                       cluster = results$`X.`,
                       method.tau = "REML",
                       hakn = TRUE)

meta:::forest.meta(m.genRD, 
              layout = "meta",
              sortvar = g,
              print.tau2 = TRUE,
              prediction = TRUE,
              leftlabs = c("Study"),
              xlim = c(-2,2),
              subgroup.name = "Research design",
               col.square = "orange",
                       plotwidth = "5.5cm",
                       col.diamond = "red",
              leftcols = c("studlab"),
              colgap.forest.left = "5cm")

m.genRD
Number of studies: k = 21

                             SMD           95%-CI    t p-value
Random effects model (HK) 0.5310 [0.2658; 0.7961] 4.18  0.0005

Quantifying heterogeneity:
 tau^2 = 0.2159 [0.1305; 0.9291]; tau = 0.4647 [0.3612; 0.9639]
 I^2 = 87.0% [81.5%; 90.9%]; H = 2.77 [2.32; 3.31]

Test of heterogeneity:
      Q d.f.  p-value
 153.86   20 < 0.0001

Results for subgroups (random effects model (HK)):
                                       k    SMD           95%-CI  tau^2    tau
Research.Design = Experimental        16 0.5671 [0.2119; 0.9223] 0.2811 0.5302
Research.Design = Quasi-experimental   5 0.4141 [0.0123; 0.8160] 0.0525 0.2291
                                          Q   I^2
Research.Design = Experimental       145.78 89.7%
Research.Design = Quasi-experimental   7.70 48.0%

Test for subgroup differences (random effects model (HK)):
                  Q d.f. p-value
Between groups 0.48    1  0.4883

Details on meta-analytical method:
- Inverse variance method
- Restricted maximum-likelihood estimator for tau^2
- Q-Profile method for confidence interval of tau^2 and tau
- Hartung-Knapp adjustment for random effects model (df = 20)

Figure 2: Subgroup by research design

Show the code
res2 = metafor::rma(results$Hedge_g,results$vi,  method="REML", mods= ~ `Research.Design`, data = results)
Binded = cbind(res2$m, res2$QM, res2$QMp, res2$QE, res2$QEp )
colnames(Binded)= c( "DF", "QM", "P", "QE", "P")
res2

Mixed-Effects Model (k = 21; tau^2 estimator: REML)

tau^2 (estimated amount of residual heterogeneity):     0.2299 (SE = 0.0913)
tau (square root of estimated tau^2 value):             0.4795
I^2 (residual heterogeneity / unaccounted variability): 88.08%
H^2 (unaccounted variability / sampling variability):   8.39
R^2 (amount of heterogeneity accounted for):            0.00%

Test for Residual Heterogeneity:
QE(df = 19) = 153.4810, p-val < .0001

Test of Moderators (coefficient 2):
QM(df = 1) = 0.1466, p-val = 0.7018

Model Results:

                                   estimate      se     zval    pval    ci.lb 
intrcpt                              0.5578  0.1334   4.1827  <.0001   0.2964 
Research.DesignQuasi-experimental   -0.1062  0.2773  -0.3829  0.7018  -0.6496 
                                    ci.ub      
intrcpt                            0.8193  *** 
Research.DesignQuasi-experimental  0.4373      

---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
Binded 
     DF        QM         P      QE                               P
[1,]  1 0.1466282 0.7017786 153.481 0.00000000000000000000004659398
Show the code
subgroup.results(m.genRD)
Subgroup k g SE 95%-CI p stars Tau2 Tau
Experimental  16 0.57 0.17 [0.212; 0.92] 0.0039 ** 0.281 0.53
Quasi-experimental 5 0.41 0.14 [0.012; 0.82] 0.0459 * 0.052 0.23

By educational level

Show the code
m.genEL <- meta::metagen(TE = Hedge_g, 
                       seTE = vi^.5,
                       studlab = `Author..year.`,
                       data = results,
                       sm = "SMD",
                       fixed = FALSE,
                       random = TRUE,
                       subgroup = results$Level.of.education,
                       cluster = results$`X.`,
                       method.tau = "REML",
                       hakn = TRUE)

meta:::forest.meta(m.genEL, 
              layout = "meta",
              sortvar = g,
              print.tau2 = TRUE,
              prediction = TRUE,
              leftlabs = c("Study"),
              xlim = c(-2,2),
              subgroup.name = "Educational level",
               col.square = "orange",
                       plotwidth = "5.5cm",
                       col.diamond = "red",
              leftcols = c("studlab"),
              colgap.forest.left = "5cm")

m.genEL
Number of studies: k = 21

                             SMD           95%-CI    t p-value
Random effects model (HK) 0.5310 [0.2658; 0.7961] 4.18  0.0005

Quantifying heterogeneity:
 tau^2 = 0.2159 [0.1305; 0.9291]; tau = 0.4647 [0.3612; 0.9639]
 I^2 = 87.0% [81.5%; 90.9%]; H = 2.77 [2.32; 3.31]

Test of heterogeneity:
      Q d.f.  p-value
 153.86   20 < 0.0001

Results for subgroups (random effects model (HK)):
                                           k    SMD            95%-CI  tau^2
Level.of.education = Secondary education   9 0.4105 [-0.0467; 0.8678] 0.3250
Level.of.education = Higher education      9 0.6845 [ 0.2489; 1.1201] 0.1072
Level.of.education = Primary education     2 0.5525 [-3.9731; 5.0780] 0.1684
Level.of.education = Early childhood       1 0.3117 [ 0.0393; 0.5841]     --
                                            tau      Q   I^2
Level.of.education = Secondary education 0.5701 113.46 92.9%
Level.of.education = Higher education    0.3274  26.13 69.4%
Level.of.education = Primary education   0.4103   2.92 65.8%
Level.of.education = Early childhood         --   0.00    --

Test for subgroup differences (random effects model (HK)):
                  Q d.f. p-value
Between groups 2.65    3  0.4491

Details on meta-analytical method:
- Inverse variance method
- Restricted maximum-likelihood estimator for tau^2
- Q-Profile method for confidence interval of tau^2 and tau
- Hartung-Knapp adjustment for random effects model (df = 20)

Figure 3: Subgroup by educational level

Show the code
res2 = metafor::rma(results$Hedge_g,results$vi,  method="REML", mods= ~ `Level.of.education`, data = results)
Binded = cbind(res2$m, res2$QM, res2$QMp, res2$QE, res2$QEp )
colnames(Binded)= c( "DF", "QM", "P", "QE", "P")
res2

Mixed-Effects Model (k = 21; tau^2 estimator: REML)

tau^2 (estimated amount of residual heterogeneity):     0.2463 (SE = 0.1029)
tau (square root of estimated tau^2 value):             0.4963
I^2 (residual heterogeneity / unaccounted variability): 88.76%
H^2 (unaccounted variability / sampling variability):   8.90
R^2 (amount of heterogeneity accounted for):            0.00%

Test for Residual Heterogeneity:
QE(df = 17) = 142.5146, p-val < .0001

Test of Moderators (coefficients 2:4):
QM(df = 3) = 1.6336, p-val = 0.6518

Model Results:

                                       estimate      se    zval    pval 
intrcpt                                  0.3117  0.5154  0.6048  0.5453 
Level.of.educationHigher education       0.4082  0.5507  0.7413  0.4585 
Level.of.educationPrimary education      0.2485  0.6571  0.3781  0.7053 
Level.of.educationSecondary education    0.0955  0.5443  0.1755  0.8607 
                                         ci.lb   ci.ub    
intrcpt                                -0.6985  1.3219    
Level.of.educationHigher education     -0.6711  1.4876    
Level.of.educationPrimary education    -1.0394  1.5363    
Level.of.educationSecondary education  -0.9713  1.1624    

---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
Binded 
     DF       QM         P       QE                              P
[1,]  3 1.633622 0.6517905 142.5146 0.0000000000000000000007077841
Show the code
subgroup.results(m.genEL)
Subgroup k g SE 95%-CI p stars Tau2 Tau
Secondary education 9 0.41 0.20 [-0.047; 0.87] 0.0722 0.33 0.57
Higher education 9 0.68 0.19 [ 0.249; 1.12] 0.0067 ** 0.11 0.33
Primary education 2 0.55 0.36 [-3.973; 5.08] 0.3646 0.17 0.41
Early childhood 1 0.31 0.14 [ 0.039; 0.58] 0.0249 * NA NA

By subject

Show the code
m.genS <- meta::metagen(TE = Hedge_g, 
                       seTE = vi^.5,
                       studlab = `Author..year.`,
                       data = results,
                       sm = "SMD",
                       fixed = FALSE,
                       random = TRUE,
                       subgroup = results$Subject,
                       cluster = results$`X.`,
                       method.tau = "REML",
                       hakn = TRUE)

meta:::forest.meta(m.genS, 
              layout = "meta",
              sortvar = g,
              print.tau2 = TRUE,
              prediction = TRUE,
              leftlabs = c("Study"),
              xlim = c(-2,2),
              subgroup.name = "Subject",
               col.square = "orange",
                       plotwidth = "5.5cm",
                       col.diamond = "red",
              leftcols = c("studlab"),
              colgap.forest.left = "5cm")

m.genS
Number of studies: k = 21

                             SMD           95%-CI    t p-value
Random effects model (HK) 0.5310 [0.2658; 0.7961] 4.18  0.0005

Quantifying heterogeneity:
 tau^2 = 0.2159 [0.1305; 0.9291]; tau = 0.4647 [0.3612; 0.9639]
 I^2 = 87.0% [81.5%; 90.9%]; H = 2.77 [2.32; 3.31]

Test of heterogeneity:
      Q d.f.  p-value
 153.86   20 < 0.0001

Results for subgroups (random effects model (HK)):
                                        k    SMD            95%-CI   tau^2
Subject = Mathematics                   6 0.1040 [-0.0646; 0.2727] <0.0001
Subject = Language                      6 0.6707 [ 0.0206; 1.3208]  0.3539
Subject = Science and Social Sciences   3 0.4351 [-0.5839; 1.4540]  0.1100
Subject = Training                      1 0.9855 [ 0.3984; 1.5725]      --
Subject = ICT & Engineering             5 0.9147 [-0.3511; 2.1804]  0.4505
                                         tau     Q   I^2
Subject = Mathematics                 0.0020  6.47 22.7%
Subject = Language                    0.5949 67.78 92.6%
Subject = Science and Social Sciences 0.3316  6.04 66.9%
Subject = Training                        --  0.00    --
Subject = ICT & Engineering           0.6712 19.62 79.6%

Test for subgroup differences (random effects model (HK)):
                   Q d.f. p-value
Between groups 15.92    4  0.0031

Details on meta-analytical method:
- Inverse variance method
- Restricted maximum-likelihood estimator for tau^2
- Q-Profile method for confidence interval of tau^2 and tau
- Hartung-Knapp adjustment for random effects model (df = 20)

Figure 4: Subgroup by subject

Show the code
res2 = metafor::rma(results$Hedge_g,results$vi,  method="REML", mods = ~Subject, data = results,intercept  = FALSE)
Binded = cbind(res2$m, res2$QM, res2$QMp, res2$QE, res2$QEp )
colnames(Binded)= c( "DF", "QM", "P", "QE", "P")
res2

Mixed-Effects Model (k = 21; tau^2 estimator: REML)

tau^2 (estimated amount of residual heterogeneity):     0.1923 (SE = 0.0855)
tau (square root of estimated tau^2 value):             0.4385
I^2 (residual heterogeneity / unaccounted variability): 85.68%
H^2 (unaccounted variability / sampling variability):   6.98
R^2 (amount of heterogeneity accounted for):            10.93%

Test for Residual Heterogeneity:
QE(df = 16) = 99.9023, p-val < .0001

Test of Moderators (coefficients 2:5):
QM(df = 4) = 6.1662, p-val = 0.1871

Model Results:

                                    estimate      se     zval    pval    ci.lb 
intrcpt                               0.8288  0.2462   3.3662  0.0008   0.3462 
SubjectLanguage                      -0.1584  0.3154  -0.5023  0.6154  -0.7767 
SubjectMathematics                   -0.6528  0.3124  -2.0897  0.0366  -1.2651 
SubjectScience and Social Sciences   -0.3707  0.3801  -0.9755  0.3293  -1.1156 
SubjectTraining                       0.1566  0.5854   0.2676  0.7890  -0.9907 
                                      ci.ub      
intrcpt                              1.3114  *** 
SubjectLanguage                      0.4598      
SubjectMathematics                  -0.0405    * 
SubjectScience and Social Sciences   0.3742      
SubjectTraining                      1.3039      

---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
Binded 
     DF       QM        P       QE                      P
[1,]  4 6.166177 0.187077 99.90235 0.00000000000003613081
Show the code
subgroup.results(m.genS)
Subgroup k g SE 95%-CI p stars Tau2 Tau
Mathematics 6 0.10 0.066 [-0.065; 0.27] 0.174 0.000004 0.002
Language 6 0.67 0.253 [ 0.021; 1.32] 0.045 * 0.353868 0.595
Science and Social Sciences 3 0.44 0.237 [-0.584; 1.45] 0.208 0.109977 0.332
Training 1 0.99 0.300 [ 0.398; 1.57] 0.001 ** NA NA
ICT & Engineering 5 0.91 0.456 [-0.351; 2.18] 0.115 0.450488 0.671

By duration

Show the code
m.genD <- meta::metagen(TE = Hedge_g, 
                       seTE = vi^.5,
                       studlab = `Author..year.`,
                       data = results,
                       sm = "SMD",
                       fixed = FALSE,
                       random = TRUE,
                       subgroup = results$Duration,
                       cluster = results$`X.`,
                       method.tau = "REML",
                       hakn = TRUE)

meta:::forest.meta(m.genD, 
              layout = "meta",
              sortvar = g,
              print.tau2 = TRUE,
              prediction = TRUE,
              leftlabs = c("Study"),
              xlim = c(-2,2),
              subgroup.name = "Duration",
               col.square = "orange",
                       plotwidth = "5.5cm",
                       col.diamond = "red",
              leftcols = c("studlab"),
              colgap.forest.left = "5cm")

m.genD
Number of studies: k = 21

                             SMD           95%-CI    t p-value
Random effects model (HK) 0.5310 [0.2658; 0.7961] 4.18  0.0005

Quantifying heterogeneity:
 tau^2 = 0.2159 [0.1305; 0.9291]; tau = 0.4647 [0.3612; 0.9639]
 I^2 = 87.0% [81.5%; 90.9%]; H = 2.77 [2.32; 3.31]

Test of heterogeneity:
      Q d.f.  p-value
 153.86   20 < 0.0001

Results for subgroups (random effects model (HK)):
                          k    SMD            95%-CI  tau^2    tau      Q   I^2
Duration = One semester  14 0.5684 [ 0.2065; 0.9303] 0.2252 0.4745 113.40 88.5%
Duration = One year       4 0.0886 [-0.1042; 0.2814]      0      0   1.84  0.0%
Duration = One month      3 1.1366 [ 0.4791; 1.7940] 0.0028 0.0528   1.70  0.0%

Test for subgroup differences (random effects model (HK)):
                   Q d.f.  p-value
Between groups 44.29    2 < 0.0001

Details on meta-analytical method:
- Inverse variance method
- Restricted maximum-likelihood estimator for tau^2
- Q-Profile method for confidence interval of tau^2 and tau
- Hartung-Knapp adjustment for random effects model (df = 20)

Figure 5: Subgroup by duration

Show the code
res2 = metafor::rma(results$Hedge_g,results$vi,  method="REML", mods = ~Duration, data = results,intercept  = FALSE)
Binded = cbind(res2$m, res2$QM, res2$QMp, res2$QE, res2$QEp )
colnames(Binded)= c( "DF", "QM", "P", "QE", "P")

# Create a dataframe for the subgroup results
subgroup.results(m.genD)
Subgroup k g SE 95%-CI p stars Tau2 Tau
One semester 14 0.568 0.168 [ 0.21; 0.93] 0.0048 ** 0.2252 0.475
One year 4 0.089 0.061 [-0.10; 0.28] 0.2399 0.0000 0.000
One month 3 1.137 0.153 [ 0.48; 1.79] 0.0176 * 0.0028 0.053