Supplement 3. Excluded studies

Supplement 4. Measures

Supplement 5. Included studies

## New names:
## * `` -> `...15`
## * `` -> `...17`
## * `` -> `...18`
## * `` -> `...20`

Supplement 6. Systematic review

Effect size calculations

Overall N studies + participants

n_sample = dat.meta.long %>% 
    summarise(n=length(unique(paste(ID_study, indep_sample))))

data.frame(n_sample=n_sample, dat_tot)
##     n n_studies n_es n_nexp_out n_exp_out
## 1 152       142  652       7983      8300

N studies (adjustment discarded)

dat.borenstein %>%
    group_by(outcome_SOC_agg) %>%
    summarise(n_es = sum(trial),
              n_exp = sum(n_exp),
              n_nexp = sum(n_nexp),
              n_study2 = length(unique(ID_study)))
## # A tibble: 5 x 5
##   outcome_SOC_agg                 n_es n_exp n_nexp n_study2
##   <chr>                          <dbl> <dbl>  <dbl>    <int>
## 1 Empathy                           31   507    560       13
## 2 Everyday social skills           225  6177   5719       87
## 3 Facial emotion recognition       188  2154   2228       45
## 4 Non-facial emotion recognition    28   522    580        9
## 5 Theory of mind                   180  2542   2455       52

N studies (adjustment splitted)

synth_n = dat.borenstein %>%
    group_by(outcome_SOC) %>%
    summarise(n_es = sum(trial),
              n_exp = sum(n_exp),
              n_nexp = sum(n_nexp),
              nstudy1 = n(),
              n_study2 = length(unique(ID_study)))
synth_n
## # A tibble: 10 x 6
##    outcome_SOC                                n_es n_exp n_nexp nstudy1 n_study2
##    <chr>                                     <dbl> <dbl>  <dbl>   <int>    <int>
##  1 Empathy  (adjusted)                           6    71     80       3        3
##  2 Empathy  (non-adjusted)                      25   436    480      12       12
##  3 Everyday social skills  (adjusted)           16   607    519       9        9
##  4 Everyday social skills  (non-adjusted)      209  5570   5200      82       82
##  5 Facial emotion recognition  (adjusted)       20   442    571       7        7
##  6 Facial emotion recognition  (non-adjuste~   168  1712   1657      42       42
##  7 Non-facial emotion recognition  (adjuste~     3   141    254       2        2
##  8 Non-facial emotion recognition  (non-adj~    25   381    326       8        8
##  9 Theory of mind  (adjusted)                   19   258    290       8        8
## 10 Theory of mind  (non-adjusted)              161  2284   2165      49       49
dat.meta.long %>% 
    group_by(outcome_SOC) %>%
    summarise(n=length(unique(paste(ID_study, indep_sample))))
## # A tibble: 10 x 2
##    outcome_SOC                                        n
##    <chr>                                          <int>
##  1 Empathy  (adjusted)                                3
##  2 Empathy  (non-adjusted)                           14
##  3 Everyday social skills  (adjusted)                 9
##  4 Everyday social skills  (non-adjusted)            86
##  5 Facial emotion recognition  (adjusted)             8
##  6 Facial emotion recognition  (non-adjusted)        44
##  7 Non-facial emotion recognition  (adjusted)         2
##  8 Non-facial emotion recognition  (non-adjusted)     8
##  9 Theory of mind  (adjusted)                         8
## 10 Theory of mind  (non-adjusted)                    52

Supplement 7. ES visualization

Distribution of ES

ggplot(dat.meta, aes(x = es_adj, y = es)) + 
  geom_jitter(alpha = 0.3, width = 0.35, size = 1/dat.meta$se) +
  geom_violin(size = 0.5, alpha = 0.5) +
theme_bw() 

Distribution of ES / outcomes

2 plots, tu choisis celui qui tu préfères

ggplot(dat.meta, aes(x = outcome_SOC_agg, y = es)) + 
      geom_jitter(width = 0.1, alpha = 0.2, aes(fill = ID, size = 1/se)) +             # geom_boxplot(trim=FALSE, alpha = 0.6) +
      facet_grid(es_adj ~ "") +
       theme_bw() +
      labs(y = "Standardized mean difference (SMD)", x = "") +
        guides(fill=FALSE) +
       coord_flip()

ggplot(dat.meta, aes(x = outcome_SOC_agg, y = es)) + 
    geom_violin(aes(fill = outcome_SOC_agg), alpha = 0.3) +
    geom_jitter(width = 0.1, alpha = 0.2, aes(fill = ID, size = 1/se)) + 
    geom_boxplot(width=0.1)+
    facet_grid(es_adj ~ "") +
    theme_bw() +
    labs(y = "Standardized mean difference (SMD)", x = "") +
    theme(text = element_text(size = 18),
          legend.position = "none",
          axis.title.y = element_text(size=12, face="bold"), 
          axis.title.x = element_text(size=12, face="bold")) +
    coord_flip()  


Supplement 8. Main analysis

Data analysis

dat.meta$outcome_MOD = ifelse(
  dat.meta$outcome_SOC_agg == "Everyday social skills",
  "Everyday social skills", "Social cognition")

dat.crude = subset(dat.meta, es_adj == " Non-Adjusted")
dat.adjusted = subset(dat.meta, es_adj == " Adjusted")

V.SCE  <- with(dat.crude,
  clubSandwich::impute_covariance_matrix(
    vi = se^2, 
    cluster = ID_study, 
    r = 0.8,
    return_list = FALSE,
    smooth_vi = TRUE, 
    subgroup = outcome_SOC))

# all.equal(dat.meta$se^2, diag(unlist(V.SCE)))

SCE <- metafor::rma.mv(yi = es, V = V.SCE, 
                       data = dat.crude, 
                       mods = ~ outcome_SOC - 1,
                       random = ~ outcome_SOC | ID_study,
                       struct = "DIAG",
                       sparse = TRUE)

SCE.ISQ <- metafor::rma.mv(yi = es, V = V.SCE, 
                       data = dat.crude, 
                       mods = ~ outcome_SOC - 1)
het = function(x, y) {
  i2 = NA
  for (i in 1:nrow(vcov(x))) {
    i2[i] = 100 * (vcov(x)[i,i] - vcov(y)[i,i]) / vcov(x)[i,i]
  }
  return(i2)
}


res.SCE <- data.frame(clubSandwich::coef_test(SCE, vcov = "CR2", cluster = dat.crude$ID_study)) # , cluster = df.ES$researchgroup
res.SCE.ci = data.frame(clubSandwich::conf_int(SCE, vcov = "CR2", cluster = dat.crude$ID_study))
res.SCE$target <- gsub("outcome_SOC", "", row.names(res.SCE))
res.SCE.ci$target <- gsub("outcome_SOC", "", row.names(res.SCE.ci))
res.SCE = dplyr::left_join(res.SCE, res.SCE.ci)
res.SCE$tau2 = SCE$tau2
res.SCE$I2 = het(SCE, SCE.ISQ)
library(clubSandwich)
# Empathy v ToM
Wald_test(SCE, 
          constraints = matrix(c(1,0,0,0,-1), nrow=1),
          vcov = "CR2", cluster = dat.crude$ID_study)
##  test Fstat df_num df_denom p_val sig
##   HTZ  2.15      1     13.7 0.165
# facial v non facial
Wald_test(SCE, 
          constraints = matrix(c(0,0,1,-1, 0), nrow=1),
          vcov = "CR2", cluster = dat.crude$ID_study)
##  test Fstat df_num df_denom  p_val sig
##   HTZ  7.13      1     12.6 0.0197   *
# soc-cog v everyday
Wald_test(SCE, 
          constraints = matrix(c(1,-1,1,1,1), nrow=1),
          vcov = "CR2", cluster = dat.crude$ID_study)
##  test Fstat df_num df_denom   p_val sig
##   HTZ  11.4      1     26.4 0.00232  **
Wald_test(SCE, 
          constraints = matrix(c(1,-1,0,0,0), nrow=1),
          vcov = "CR2", cluster = dat.crude$ID_study)
##  test Fstat df_num df_denom  p_val sig
##   HTZ   8.7      1     13.6 0.0108   *
Wald_test(SCE, 
          constraints = matrix(c(0,-1,1,0,0), nrow=1),
          vcov = "CR2", cluster = dat.crude$ID_study)
##  test Fstat df_num df_denom  p_val sig
##   HTZ    29      1     81.7 <0.001 ***
Wald_test(SCE, 
          constraints = matrix(c(0,-1,0,1,0), nrow=1),
          vcov = "CR2", cluster = dat.crude$ID_study)
##  test Fstat df_num df_denom  p_val sig
##   HTZ  41.7      1       12 <0.001 ***
Wald_test(SCE, 
          constraints = matrix(c(0,-1,0,0,1), nrow=1),
          vcov = "CR2", cluster = dat.crude$ID_study)
##  test Fstat df_num df_denom  p_val sig
##   HTZ    14      1     93.5 <0.001 ***
res_main <- left_join(res.SCE, dat_SOC)
## Joining, by = "target"
res_main$p_Satt_bonferroni = res_main$p_Satt * 8
res_main$raw_outcome <- gsub(r"{\s*\([^\)]+\)}","",
                            as.character(res_main$outcome_SOC))

res_main$outcome_SOC <- gsub("social", "Social", res_main$outcome_SOC)
res_main$outcome_SOC <- gsub("skill", "Skill", res_main$outcome_SOC)
res_main$outcome_SOC <- gsub("emotion", "Emotion", res_main$outcome_SOC)
res_main$outcome_SOC <- gsub("recognition", "Recognition", res_main$outcome_SOC)
res_main$outcome_SOC <- gsub("mind", "Mind", res_main$outcome_SOC)
# res_main$outcome_SOC <- factor(res_main$outcome_SOC, 
#          levels=c('Theory of Mind (non-adjusted)',
#                   'Theory of Mind (adjusted)',
#                   'Empathy (non-adjusted)', 
#                   'Empathy (adjusted)', 
#                   'Facial Emotion Recognition (non-adjusted)',
#                   'Facial Emotion Recognition (adjusted)',
#                   'Non-facial Emotion Recognition (non-adjusted)',
#                   'Non-facial Emotion Recognition (adjusted)',
#                   'Everyday Social Skills (non-adjusted)',
#                   'Everyday Social Skills (adjusted)'))

res_main[,c("beta", "SE", "tstat", "df", "p_Satt",
            "p_Satt_bonferroni", "CI_L", "CI_U", "tau2", "I2", 
            "n_studies",    "n_nexp_out" , "n_exp_out")] <- apply(
res_main[,c("beta", "SE", "tstat", "df", "p_Satt",
            "p_Satt_bonferroni", "CI_L", "CI_U", "tau2", "I2", 
            "n_studies",    "n_nexp_out" , "n_exp_out")], 2, function(x) round(x, 3))

res_main <- res_main[order(res_main$outcome_SOC), ]
DT::datatable(res_main, 
              rownames = FALSE,
              extensions = 'Buttons',
              options = list(  # options
                buttons = c('copy', 'excel'),
                scrollX = TRUE,
                dom = c('ftB'), 
                autoWidth = TRUE,
                columnDefs = list(
                  list(className = 'dt-center', 
                                     targets = "_all"))))

Forest plot

res_main$SE_COR = (res_main$CI_U - res_main$CI_L) / (3.92)


res_main$raw_outcome_save = res_main$raw_outcome
# res_main$raw_outcome = res_main$raw_outcome_save
res_main$raw_outcome <- factor(res_main$raw_outcome, 
         levels=c('Theory of mind',
                  'Empathy', 
                  'Facial emotion recognition',
                  'Non-facial emotion recognition',
                  'Everyday social skills'))

tab.plot <- data.frame(
  Outcome = do.call(rbind, lapply(res_main$outcome_SOC, 
                                  function(x) paste(strwrap(x, width = 60), 
                                                    collapse = "\n"))),
  n_ADHD = res_main$n_exp_out,
  n_nexpT = res_main$n_nexp_out,
  n_studies = res_main$n_studies,
  tau2 = res_main$tau2,
  I2 = paste0(round(res_main$I2), "%"))

value_num_plot = data.frame(apply(res_main[, c("beta", "SE_COR")], 2, function(x) as.numeric(as.character(x))))

forest_modif(x = value_num_plot[ ,c("beta", "SE_COR")], 
           variant = "classic",
           col = "Greys", xlab = "SMD", annotate_CI = TRUE,
           study_table = tab.plot,
           group = res_main$raw_outcome,
           type = "study_only",
           text_size = 3.5,
           x_limit = c(-0.5, 1.5),
           N = tab.plot$n_ADHD + tab.plot$n_nexpT,
           x_breaks = seq(-3, 3, 0.5)
           )

Diagnostics

# , eval = FALSE
# windows() ## create window to plot your file, eval = FALSE
metafor::profile.rma.mv(SCE)
# dev.off()

Supplement 9. Supplementary analyses

9.1. Other statistical approaches

A. Borenstein

dat.borenstein.analysis = subset(dat.borenstein, es_adj == " Non-Adjusted")

meta.reg <- metafor::rma.mv(yi = es, V = se^2, 
                           data = dat.borenstein.analysis, 
                           random = ~ outcome_SOC | ID_study,
                           struct = "DIAG",
                           mods = ~ outcome_SOC - 1)

res.S1.a.clean = data.frame(
  beta = meta.reg$beta,
  se = meta.reg$se,
  ci_lo = meta.reg$ci.lb,
  ci_up = meta.reg$ci.ub,
  pval = meta.reg$pval, 
  target = gsub("outcome_SOC", "", row.names(meta.reg$b)))

res.S1 <- left_join(res.S1.a.clean, dat_SOC)
## Joining, by = "target"
DT::datatable(res.S1, 
              rownames = FALSE,
              extensions = 'Buttons',
              options = list(  # options
                buttons = c('copy', 'excel'),
                scrollX = TRUE,
                dom = c('ftB'), 
                autoWidth = TRUE,
                columnDefs = list(
                  list(className = 'dt-center', 
                                     targets = "_all"))))

B. RVE approach

robu.main <- robumeta::robu(es ~ outcome_SOC - 1, 
                            data = dat.crude, 
                            studynum = ID_study,
                            var.eff.size = se^2,
                            modelweights = "CORR",
                            small = TRUE,
                            rho = 0.8)

dat_robu_main = data.frame(
  beta = robu.main$reg_table$b.r,
  se = robu.main$reg_table$SE,
  ci_lo = robu.main$reg_table$CI.L,
  ci_up = robu.main$reg_table$CI.U,
  pval = robu.main$reg_table$prob, 
  target = gsub("outcome_SOC", "", row.names(meta.reg$b)),
  target2 = robu.main$reg_table$labels)

DT::datatable(dat_robu_main, 
              rownames = FALSE,
              extensions = 'Buttons',
              options = list(  # options
                buttons = c('copy', 'excel'),
                scrollX = TRUE,
                dom = c('ftB'), 
                autoWidth = TRUE,
                columnDefs = list(
                  list(className = 'dt-center', 
                                     targets = "_all"))))

C. SCE vs RVE vs Borenstein

res.SCE.main = data.frame(
    beta = res.SCE$beta,
    se = res.SCE$SE,
    ci_lo = res.SCE$CI_L,
    ci_up = res.SCE$CI_U,
    pval = res.SCE$p_Satt, 
    target =res.SCE$target)
res.SCE.main$Analysis = "SCE approach"
res.S1.a.clean$Analysis = "Borenstein approach"
dat_robu_main$Analysis = "RVE approach"
dat_forest_S1 = bind_rows(res.SCE.main,
                          res.S1.a.clean,
                          dat_robu_main)


meta_res_tot = meta::metagen(TE = beta, seTE = (ci_up-ci_lo)/(2*qnorm(.975)), 
                             sm = "SMD", data = dat_forest_S1,
                             subgroup = target, 
                             studlab = Analysis)

meta::forest(meta_res_tot, random = FALSE, fixed = FALSE, 
             leftcols = c("studlab"),
             text.subgroup.nohet = FALSE, print.tau2 = FALSE, print.I2 = FALSE, print.pval.Q = FALSE,
             plotwidth = "15cm", colgap.left = "1cm", colgap.right = "1cm",
             leftlabs= c(""),
             just = "right", spacing = 0.8)

9.2. Small study effects

A. Nakagawa approach

dat.crude$inv_n_tilda <- with(dat.crude, (n_nexp + n_exp)/(n_nexp*n_exp))
dat.crude$sqrt_inv_n_tilda <- with(dat.crude, sqrt(inv_n_tilda))

nak.pb = metafor::rma.mv(yi = es, V = V.SCE, 
                      data = dat.crude, 
                      mods = ~ 1 + sqrt_inv_n_tilda + outcome_SOC,
                      random = ~ outcome_SOC | ID_study,
                      struct = "DIAG",
                                            test = "t", 
                      control=list(optimizer="optim", optmethod="Nelder-Mead"),
sparse = TRUE)
clubSandwich::coef_test(nak.pb, vcov = "CR2", cluster = dat.crude$ID_study)
##                                                       Coef. Estimate    SE
## 1                                                   intrcpt   -0.693 0.545
## 2                                          sqrt_inv_n_tilda    4.848 1.893
## 3         outcome_SOCEveryday social skills  (non-adjusted)    0.819 0.256
## 4     outcome_SOCFacial emotion recognition  (non-adjusted)    0.121 0.255
## 5 outcome_SOCNon-facial emotion recognition  (non-adjusted)   -0.105 0.264
## 6                 outcome_SOCTheory of mind  (non-adjusted)    0.314 0.212
##   t-stat d.f. p-val (Satt) Sig.
## 1 -1.272 14.5      0.22355     
## 2  2.561 16.7      0.02046    *
## 3  3.199 13.6      0.00663   **
## 4  0.475 15.2      0.64163     
## 5 -0.399 14.4      0.69559     
## 6  1.479 14.7      0.16022

B. PET-PEESE approach

PET = metafor::rma.mv(yi = es, V = V.SCE, 
                      data = dat.crude, 
                      mods = ~ se  + outcome_SOC,
                      random = ~ outcome_SOC | ID_study,
                      struct = "DIAG",
                      sparse = TRUE)
clubSandwich::coef_test(PET, vcov = "CR2", 
                        cluster = dat.crude$ID_study)
##                                                       Coef. Estimate    SE
## 1                                                   intrcpt  -1.2001 0.781
## 2                                                        se   6.5829 2.806
## 3         outcome_SOCEveryday social skills  (non-adjusted)   0.7548 0.228
## 4     outcome_SOCFacial emotion recognition  (non-adjusted)   0.1471 0.236
## 5 outcome_SOCNon-facial emotion recognition  (non-adjusted)   0.0225 0.266
## 6                 outcome_SOCTheory of mind  (non-adjusted)   0.2486 0.199
##    t-stat  d.f. p-val (Satt) Sig.
## 1 -1.5369 11.98      0.15030     
## 2  2.3459  8.42      0.04547    *
## 3  3.3091 13.95      0.00519   **
## 4  0.6219 16.20      0.54265     
## 5  0.0846 15.05      0.93371     
## 6  1.2495 15.30      0.23024
dat.crude$var = dat.crude$se^2
PET = metafor::rma.mv(yi = es, V = V.SCE, 
                      data = dat.crude, 
                      mods = ~ var  + outcome_SOC,
                      random = ~ outcome_SOC | ID_study,
                      struct = "DIAG",
                      sparse = TRUE)
clubSandwich::coef_test(PET, vcov = "CR2", 
                        cluster = dat.crude$ID_study)
##                                                       Coef. Estimate    SE
## 1                                                   intrcpt    0.241 0.343
## 2                                                       var    4.206 3.639
## 3         outcome_SOCEveryday social skills  (non-adjusted)    0.676 0.213
## 4     outcome_SOCFacial emotion recognition  (non-adjusted)    0.100 0.221
## 5 outcome_SOCNon-facial emotion recognition  (non-adjusted)   -0.178 0.239
## 6                 outcome_SOCTheory of mind  (non-adjusted)    0.256 0.178
##   t-stat  d.f. p-val (Satt) Sig.
## 1  0.705 11.05       0.4956     
## 2  1.156  2.66       0.3409     
## 3  3.169 13.49       0.0071   **
## 4  0.454 15.19       0.6565     
## 5 -0.745 15.12       0.4677     
## 6  1.441 13.88       0.1719

C. Egger’s test for each outcome

dat_egger = data.frame(
  meta_review = "Haza",
  study = dat.borenstein.analysis$ID_study,
  factor = dat.borenstein.analysis$outcome_SOC,
  value = dat.borenstein.analysis$es,
  se = dat.borenstein.analysis$se,
  n_cases = dat.borenstein.analysis$n_exp,
  n_controls = dat.borenstein.analysis$n_nexp,
  measure = "G")
  
umb = metaumbrella::umbrella(dat_egger)
## Analyzing factor: Theory of mind  (non-adjusted) 
## Analyzing factor: Everyday social skills  (non-adjusted) 
## Analyzing factor: Facial emotion recognition  (non-adjusted) 
## Analyzing factor: Non-facial emotion recognition  (non-adjusted) 
## Analyzing factor: Empathy  (non-adjusted)
umb
## 
## Umbrella review:
##                                           Factor n_studies total_n n_cases
## 1                 Theory of mind  (non-adjusted)        49    4449    2284
## 2         Everyday social skills  (non-adjusted)        82   10770    5570
## 3     Facial emotion recognition  (non-adjusted)        42    3369    1712
## 4 Non-facial emotion recognition  (non-adjusted)         8     707     381
## 5                        Empathy  (non-adjusted)        12     916     436
##   n_controls measure value       value_CI    eG          eG_CI   eOR
## 1       2165       G 0.834  [0.68, 0.988] 0.834  [0.68, 0.988] 4.539
## 2       5200       G 1.224 [1.081, 1.366] 1.224 [1.081, 1.366] 9.201
## 3       1657       G 0.629  [0.46, 0.798] 0.629  [0.46, 0.798] 3.129
## 4        326       G 0.323  [0.076, 0.57] 0.323  [0.076, 0.57] 1.795
## 5        480       G 0.563 [0.149, 0.977] 0.563 [0.149, 0.977] 2.776
##           eOR_CI  p_value     I2           PI_eG          PI_eOR  egger_p
## 1 [3.434, 5.998] 2.11e-26 78.946 [-0.145, 1.813] [0.769, 26.795] 4.03e-01
## 2  [7.1, 11.923] 3.18e-63 88.756  [0.006, 2.441] [1.011, 83.755] 7.16e-05
## 3 [2.303, 4.252] 3.04e-13 86.203 [-0.398, 1.656] [0.486, 20.141] 7.97e-01
## 4 [1.147, 2.811] 1.05e-02 60.343  [-0.42, 1.066]  [0.467, 6.909] 4.20e-02
## 5 [1.311, 5.881] 7.67e-03 85.329 [-1.026, 2.152] [0.155, 49.577] 2.66e-01
##      ESB_p power_med     JK_p   largest_CI_eG   largest_CI_eOR rob amstar
## 1 5.47e-01       100 4.66e-25  [0.478, 1.536]  [2.379, 16.202]  NA     NA
## 2 1.42e-02       100 2.41e-61  [0.421, 0.722]   [2.145, 3.707]  NA     NA
## 3 9.48e-01       100 1.75e-12  [1.684, 2.302] [21.228, 65.088]  NA     NA
## 4 4.10e-01       100 3.37e-02 [-0.282, 0.333]      [0.6, 1.83]  NA     NA
## 5 6.64e-01       100 1.95e-02    [0.02, 0.77]   [1.036, 4.044]  NA     NA

9.3. Type of publication

dat.publi = subset(dat.crude, Type_publication %in% 
                     c("Article", "Thèse"))
V.SCE.publi  <- with(dat.publi,
  clubSandwich::impute_covariance_matrix(
    vi = se^2, 
    cluster = ID_study, 
    r = 0.8,
    return_list = FALSE,
    smooth_vi = TRUE, 
    subgroup = outcome_SOC))

SCE.publi <- metafor::rma.mv(yi = es, V = V.SCE.publi, 
                       data = dat.publi, 
                       mods = ~ Type_publication,
                       random = ~ outcome_SOC | ID_study,
                       struct = "DIAG",
                       sparse = TRUE)

clubSandwich::coef_test(SCE.publi, vcov = "CR2", cluster = dat.publi$ID_study)
##                   Coef. Estimate    SE t-stat d.f. p-val (Satt) Sig.
## 1               intrcpt    0.875 0.057 15.340 94.4       <0.001  ***
## 2 Type_publicationThèse    0.100 0.131  0.765 10.4        0.461
SCE.publi <- metafor::rma.mv(yi = es, V = V.SCE.publi, 
                       data = dat.publi, 
                       mods = ~ Type_publication - 1,
                       random = ~ outcome_SOC | ID_study,
                       struct = "DIAG",
                       sparse = TRUE)
clubSandwich::coef_test(SCE.publi, vcov = "CR2", cluster = dat.publi$ID_study)
##                     Coef. Estimate    SE t-stat  d.f. p-val (Satt) Sig.
## 1 Type_publicationArticle    0.875 0.057  15.34 94.35       <0.001  ***
## 2   Type_publicationThèse    0.975 0.118   8.25  8.39       <0.001  ***
SCE.publi <- metafor::rma.mv(yi = es, V = V.SCE.publi, 
                       data = dat.publi, 
                       mods = ~ Type_publication - 1,
                       random = ~ outcome_SOC | ID_study,
                       struct = "DIAG",
                       sparse = TRUE)
clubSandwich::coef_test(SCE.publi, vcov = "CR2", cluster = dat.publi$ID_study)
##                     Coef. Estimate    SE t-stat  d.f. p-val (Satt) Sig.
## 1 Type_publicationArticle    0.875 0.057  15.34 94.35       <0.001  ***
## 2   Type_publicationThèse    0.975 0.118   8.25  8.39       <0.001  ***
SCE.publi <- metafor::rma.mv(yi = es, V = V.SCE.publi, 
                       data = dat.publi, 
                       mods = ~ Type_publication:outcome_MOD - 1,
                       random = ~ outcome_SOC | ID_study,
                       struct = "DIAG",
                       sparse = TRUE)
clubSandwich::coef_test(SCE.publi, vcov = "CR2", cluster = dat.publi$ID_study)
##                                                       Coef. Estimate     SE
## 1 Type_publicationArticle:outcome_MODEveryday social skills    1.153 0.0745
## 2   Type_publicationThèse:outcome_MODEveryday social skills    1.498 0.1820
## 3       Type_publicationArticle:outcome_MODSocial cognition    0.691 0.0747
## 4         Type_publicationThèse:outcome_MODSocial cognition    0.692 0.2263
##   t-stat  d.f. p-val (Satt) Sig.
## 1  15.49 69.20       <0.001  ***
## 2   8.23  7.80       <0.001  ***
## 3   9.26 55.89       <0.001  ***
## 4   3.06  6.27       0.0211    *

9.4. Adjustment for covariates

V.SCE.adjusted  <- with(dat.adjusted,
  clubSandwich::impute_covariance_matrix(
    vi = se^2, 
    cluster = ID_study, 
    r = 0.8,
    return_list = FALSE,
    smooth_vi = TRUE, 
    subgroup = outcome_SOC))


SCE.adjusted <- metafor::rma.mv(yi = es, V = V.SCE.adjusted, 
                          data = dat.adjusted, 
                          mods = ~ outcome_SOC - 1,
                          random = ~ outcome_SOC | ID_study,
                          struct = "DIAG",
                          sparse = TRUE)
clubSandwich::coef_test(SCE.adjusted, vcov = "CR2", cluster = dat.adjusted$ID_study)
##                                                   Coef. Estimate     SE t-stat
## 1                        outcome_SOCEmpathy  (adjusted)    0.701 0.4286   1.64
## 2         outcome_SOCEveryday social skills  (adjusted)    1.416 0.1991   7.11
## 3     outcome_SOCFacial emotion recognition  (adjusted)    0.533 0.2055   2.59
## 4 outcome_SOCNon-facial emotion recognition  (adjusted)    0.166 0.0282   5.89
## 5                 outcome_SOCTheory of mind  (adjusted)    0.848 0.1540   5.51
##   d.f. p-val (Satt) Sig.
## 1 2.00       0.2438     
## 2 7.90       <0.001  ***
## 3 5.98       0.0412    *
## 4 1.00       0.1071     
## 5 6.84       <0.001  ***

9.5. Type of tools

dat.tool = subset(dat.crude, !is.na(Type_mesure) & outcome_SOC== "Theory of mind  (non-adjusted)")
dat.tool$vi = dat.tool$se^2
dat.tool$es_id = 1:nrow(dat.tool)
SCE.S11 <- metafor::rma.mv(yi = es, V = vi, 
                          data = dat.tool, 
                          mods = ~ Type_mesure ,
                          random = ~ 1 | ID_study/es_id)
clubSandwich::coef_test(SCE.S11, vcov = "CR2", cluster = dat.tool$ID_study)
##               Coef. Estimate     SE t-stat  d.f. p-val (Satt) Sig.
## 1           intrcpt    0.781 0.0794   9.83 45.00       <0.001  ***
## 2 Type_mesureReport    0.478 0.2348   2.04  7.34       0.0794    .
SCE.S11wi <- metafor::rma.mv(yi = es, V = vi, 
                          data = dat.tool, 
                          mods = ~ Type_mesure - 1,
                          random = ~ 1 | ID_study/es_id)
clubSandwich::coef_test(SCE.S11wi, vcov = "CR2", cluster = dat.tool$ID_study)
##                 Coef. Estimate     SE t-stat  d.f. p-val (Satt) Sig.
## 1 Type_mesureParadigm    0.781 0.0794   9.83 45.00       <0.001  ***
## 2   Type_mesureReport    1.259 0.2345   5.37  8.99       <0.001  ***

9.6. Risk of bias

dat.risk = subset(dat.crude,
                  Risque_biais_inclusion == "1")
V.SCE.risk  <- with(dat.risk,
  clubSandwich::impute_covariance_matrix(
    vi = se^2, 
    cluster = ID_study, 
    r = 0.8,
    return_list = FALSE,
    smooth_vi = TRUE, 
    subgroup = outcome_SOC))

SCE.risk <- metafor::rma.mv(yi = es, V = V.SCE.risk, 
                       data = dat.risk, 
                       mods = ~ outcome_SOC - 1,
                       random = ~ outcome_SOC | ID_study,
                       struct = "DIAG",
                       sparse = TRUE)

clubSandwich::coef_test(SCE.risk, vcov = "CR2", cluster = dat.risk$ID_study)
##                                                       Coef. Estimate    SE
## 1                        outcome_SOCEmpathy  (non-adjusted)    0.813 0.463
## 2         outcome_SOCEveryday social skills  (non-adjusted)    1.386 0.121
## 3     outcome_SOCFacial emotion recognition  (non-adjusted)    0.771 0.154
## 4 outcome_SOCNon-facial emotion recognition  (non-adjusted)    0.301 0.211
## 5                 outcome_SOCTheory of mind  (non-adjusted)    0.895 0.127
##   t-stat  d.f. p-val (Satt) Sig.
## 1   1.76  3.99        0.154     
## 2  11.42 33.73       <0.001  ***
## 3   5.02 14.89       <0.001  ***
## 4   1.43  1.97        0.291     
## 5   7.03 24.72       <0.001  ***

9.7. Effect of comorbidities

R = dat.borenstein   %>%
  group_by(ID_study) %>%
  slice(1) 


sum(R$n_exp)
## [1] 8095
sum(R$n_nexp)
## [1] 7785
dat.crude.S7 = subset(dat.crude, comor_ASD == "no-ASD")
dat.crude.S7.ASD = subset(dat.crude, comor_ASD == "ASD")
dat.ajd.S7.ASD = subset(dat.adjusted, comor_ASD == "ASD")
unique(c(dat.crude.S7.ASD$ID_study, dat.ajd.S7.ASD$ID_study))
##  [1] "Azadi Sohi_2011"  "Berenguer_2018"   "Craig _2015"      "Liu_2021"        
##  [5] "Mouti_2019"       "Oerlemans_2014"   "Sinzig_2008"      "Stephens_2021"   
##  [9] "Stordeur_2019"    "Suing_2014"       "Aiello_2021"      "Manteris_2011"   
## [13] "NeuroIMAGE_study"
length(unique(dat.crude.S7$ID_study))
## [1] 133
length(unique(dat.crude.S7.ASD$ID_study))
## [1] 10
V.SCE.S7  <- with(dat.crude.S7,
  clubSandwich::impute_covariance_matrix(
    vi = se^2,
    cluster = ID_study,
    r = 0.8,
    return_list = FALSE,
    smooth_vi = TRUE,
    subgroup = outcome_SOC))

SCE.S7 <- metafor::rma.mv(yi = es, V = V.SCE.S7,
                          data = dat.crude.S7,
                          mods = ~ outcome_SOC,
                          random = ~ outcome_SOC | ID_study,
                          struct = "DIAG",
                          sparse = TRUE)
clubSandwich::coef_test(SCE.S7, vcov = "CR2", 
                        cluster = dat.crude.S7$ID_study)
##                                                       Coef. Estimate    SE
## 1                                                   intrcpt   0.5637 0.211
## 2         outcome_SOCEveryday social skills  (non-adjusted)   0.5943 0.224
## 3     outcome_SOCFacial emotion recognition  (non-adjusted)   0.0906 0.228
## 4 outcome_SOCNon-facial emotion recognition  (non-adjusted)  -0.2031 0.253
## 5                 outcome_SOCTheory of mind  (non-adjusted)   0.2476 0.183
##   t-stat d.f. p-val (Satt) Sig.
## 1  2.669 10.9       0.0219    *
## 2  2.654 13.4       0.0195    *
## 3  0.397 14.6       0.6971     
## 4 -0.803 16.6       0.4333     
## 5  1.352 13.3       0.1991

Raw data

rawdata <- readxl::read_excel("G:/.shortcut-targets-by-id/1aQ8-ovwu-kQaKU1pgnyTKuT3yuRGuhr2/Revue_cognition.sociale_TDAH/shared_data_Haza_et_al.xlsx") %>% filter(!is.na(author))
# 
DT::datatable(rawdata,
              rownames = FALSE,
              extensions = 'Buttons',
              options = list(  # options
                  buttons = c('copy', 'excel'),
                  scrollX = TRUE,
                  dom = c('ftB'),
                  autoWidth = TRUE,
                  columnDefs = list(
                      list(className = 'dt-center',
                           targets = "_all"))))