Skip to content
Prev 5624 / 5632 Next

[R-meta] vcalc() for different rho by design (within=.7 vs between=.5)

Hi all,

Quick question about metafor::vcalc(): is there a way to specify different within-study correlations for sampling errors depending on study design (e.g., rho = 0.5 for between-subject studies and rho = 0.7 for within-subject studies), rather than using my likely inefficient workaround using clubSandwich::pattern_covariance_matrix() to build V?

I?m currently doing this (toy example below) and would appreciate any guidance on whether vcalc() can handle this directly.

Thanks in advance!

Zhouhan

library(metafor); library(tidyverse); library(clubSandwich)

dat.smc <- read.table(header=T, text="
study time_interval   group      ni   mpre    mpost  sdpre  sdpost  design    age
A     pre-post1       treat      28   0.89     5.07   1.40   3.20   between   adult
A     pre-post2       treat      28   0.89     3.64   1.40   3.15   between   adult
A     pre-post1       contl      58   1.22     3.52   1.76   2.58   between   young
A     pre-post2       contl      58   1.22     2.86   1.76   2.80   between   young
B     pre-post1       treat      38   1.89     4.07   0.40   2.20   within    young
B     pre-post1       contl      48   2.22     2.52   0.76   1.58   within    young")

datT <- escalc("SMCRP", ni=ni, m1i=mpost, m2i=mpre, sd1i=sdpre, sd2i=sdpost, ri=rep(.7,3), data=subset(dat.smc,group=="treat"))

datC <- escalc("SMCRP", ni=ni, m1i=mpost, m2i=mpre, sd1i=sdpre, sd2i=sdpost, ri=rep(.7,3), data=subset(dat.smc,group=="contl"))

arm <- "group"
id  <- c("study","time_interval")

dat <- datT %>%
  select(all_of(c(id, "yi", "vi")), everything()) %>%
  left_join(datC %>% select(all_of(id), yiC = yi, viC = vi), by = id) %>%
  mutate(yi = yi - yiC, vi = vi + viC, effect = row_number()) %>%
  select(-yiC, -viC)

# Define larger correlations among effect sizes from within-subjects (0.7)
# than those from between-subjects designs (0.5)
dat2 <- dat %>%
  group_by(study) %>%
  mutate(rho_study = if_else(first(design) == "within", 0.7, 0.5)) %>%
  ungroup()

r_pat <- matrix(c(
  0.7, 0.5,
  0.5, 0.5
), nrow = 2, byrow = TRUE,
dimnames = list(c("within","between"), c("within","between")))

V <- with(dat2, pattern_covariance_matrix(
  vi = vi, cluster = study, pattern_level = design, r_pattern = r_pat, check_PD = TRUE))

m <- rma.mv<http://rma.mv>(yi ~ 0 + time_interval, V, random = ~1|study/effect, data=dat2)