
Within-Study Variance-Covariance Metrics in MARS
mars authors
2026-06-09
Within-Study-VarCov-Metrics.RmdThis vignette shows examples of all currently supported
varcov_type metric options for within-study
variance-covariance computation in mars.
library(mars)1. Correlation Metrics
For synthesized correlation matrices, use:
simpleweightedaverage
cor_dat <- data.frame(
study = c("s1", "s1", "s1", "s2", "s2", "s2"),
numID = c(1, 2, 3, 1, 2, 3),
ri = c(0.20, 0.12, 0.08, 0.25, 0.15, 0.11),
N = c(100, 100, 100, 120, 120, 120)
)
S_cor_simple <- mars:::within_varcov(
data = cor_dat,
N = "N",
effect_name = "ri",
study = "study",
type = "simple"
)
S_cor_weighted <- mars:::within_varcov(
data = cor_dat,
N = "N",
effect_name = "ri",
study = "study",
type = "weighted"
)
S_cor_average <- mars:::within_varcov(
data = cor_dat,
N = "N",
effect_name = "ri",
study = "study",
type = "average"
)
S_cor_simple[[1]]
#> [,1] [,2] [,3]
#> [1,] 0.009216000 0.000643776 0.001069184
#> [2,] 0.000643776 0.009714074 0.001913318
#> [3,] 0.001069184 0.001913318 0.009872410
S_cor_weighted[[1]]
#> [,1] [,2] [,3]
#> [1,] 0.0089936224 0.0007533087 0.001179743
#> [2,] 0.0007533087 0.0096315569 0.002148884
#> [3,] 0.0011797431 0.0021488845 0.009815143
S_cor_average[[1]]
#> [,1] [,2] [,3]
#> [1,] 0.0090131289 0.0007445448 0.001170920
#> [2,] 0.0007445448 0.0096388215 0.002129556
#> [3,] 0.0011709204 0.0021295562 0.0098203152. SMD by Outcome (existing)
For multiple SMD outcomes within study, use:
outcome
smd_outcome_dat <- data.frame(
study = c("s1", "s1", "s2", "s2"),
d = c(0.30, 0.42, 0.20, 0.27),
nt = c(40, 40, 36, 36),
nc = c(40, 40, 36, 36),
r2do = c(0.7, 0.7, 0.7, 0.7)
)
S_smd_outcome <- mars:::within_varcov(
data = smd_outcome_dat,
N = NULL,
effect_name = "d",
study = "study",
type = "outcome"
)
S_smd_outcome[[1]]
#> [,1] [,2]
#> [1,] 0.05056250 0.03538587
#> [2,] 0.03538587 0.051102503. SMD with Shared Control Group
For multiple treatment arms sharing one control within study, use:
-
smd_shared_control(aliases:smd_control,control)
smd_shared_dat <- data.frame(
study = c("s1", "s1", "s2", "s2"),
effID = c(1, 2, 1, 2),
yi = c(0.22, 0.35, 0.18, 0.28),
nt = c(50, 55, 48, 46),
nc = c(60, 60, 52, 52),
control_id = c("c1", "c1", "c2", "c2")
)
S_smd_control <- mars:::within_varcov(
data = smd_shared_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "smd_shared_control"
)
S_smd_control[[1]]
#> [,1] [,2]
#> [1,] 0.03688667 0.01730833
#> [2,] 0.01730833 0.035381094. Log Relative Risk (shared control)
Use:
-
log_rr(aliases:rr,relative_risk,risk_ratio)
Required columns are treatment/control events and totals (for
example, tpos, tneg, cpos,
cneg), or equivalent aliases.
rr_dat <- data.frame(
study = c("s1", "s1", "s2", "s2"),
effID = c(1, 2, 1, 2),
tpos = c(20, 18, 16, 14),
tneg = c(30, 37, 32, 30),
cpos = c(15, 15, 14, 14),
cneg = c(45, 45, 38, 38),
control_id = c("c1", "c1", "c2", "c2")
)
nt <- rr_dat$tpos + rr_dat$tneg
nc <- rr_dat$cpos + rr_dat$cneg
rr_dat$yi <- log((rr_dat$tpos / nt) / (rr_dat$cpos / nc))
S_log_rr <- mars:::within_varcov(
data = rr_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "log_rr"
)
S_log_rr[[1]]
#> [,1] [,2]
#> [1,] 0.08 0.05000000
#> [2,] 0.05 0.087373745. Log Odds Ratio (shared control)
Use:
-
log_or(aliases:or,log_odds_ratio)
or_dat <- rr_dat
or_dat$yi <- log((or_dat$tpos / or_dat$tneg) / (or_dat$cpos / or_dat$cneg))
S_log_or <- mars:::within_varcov(
data = or_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "log_or"
)
S_log_or[[1]]
#> [,1] [,2]
#> [1,] 0.17222222 0.08888889
#> [2,] 0.08888889 0.171471476. Single-arm Proportions
Use:
-
proportion(alias:prop)
Required columns: events and totals (for example,
events, n).
prop_dat <- data.frame(
study = c("s1", "s1", "s2", "s2"),
effID = c(1, 2, 1, 2),
events = c(14, 18, 10, 13),
n = c(60, 62, 55, 57)
)
prop_dat$yi <- prop_dat$events / prop_dat$n
S_prop <- mars:::within_varcov(
data = prop_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "proportion"
)
S_prop[[1]]
#> [,1] [,2]
#> [1,] 0.002981481 0.000000000
#> [2,] 0.000000000 0.0033231517. Proportion Differences / Risk Difference (shared control)
Use:
-
proportion_diff(aliases:prop_diff,risk_difference)
pd_dat <- rr_dat
nt <- pd_dat$tpos + pd_dat$tneg
nc <- pd_dat$cpos + pd_dat$cneg
pd_dat$yi <- (pd_dat$tpos / nt) - (pd_dat$cpos / nc)
S_prop_diff <- mars:::within_varcov(
data = pd_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "proportion_diff"
)
S_prop_diff[[1]]
#> [,1] [,2]
#> [1,] 0.007925 0.003125000
#> [2,] 0.003125 0.0071280058. Continuous Outcomes with Shared Controls
For raw mean differences and log response ratios with multiple treatment arms sharing one control, use:
-
mean_diff(aliases:raw_mean_diff,md) -
log_response_ratio(aliases:response_ratio,rom,lnrr_continuous)
These structures use treatment/control sample sizes and standard deviations; log response ratios also use treatment/control means.
cont_dat <- data.frame(
study = c("s1", "s1", "s2", "s2"),
control_id = c("c1", "c1", "c2", "c2"),
mt = c(5.8, 6.1, 5.2, 5.4),
mc = c(4.6, 4.6, 4.4, 4.4),
sdt = c(1.4, 1.5, 1.3, 1.2),
sdc = c(1.2, 1.2, 1.1, 1.1),
nt = c(45, 48, 42, 41),
nc = c(50, 50, 44, 44)
)
cont_dat$yi <- cont_dat$mt - cont_dat$mc
S_md <- mars:::within_varcov(
data = cont_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "mean_diff"
)
cont_dat$yi <- log(cont_dat$mt / cont_dat$mc)
S_rom <- mars:::within_varcov(
data = cont_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "log_response_ratio"
)
S_md[[1]]
#> [,1] [,2]
#> [1,] 0.07235556 0.028800
#> [2,] 0.02880000 0.075675
S_rom[[1]]
#> [,1] [,2]
#> [1,] 0.002655814 0.001361059
#> [2,] 0.001361059 0.0026208019. Standardized Mean Change / Repeated Measures
For pre-post standardized mean change effects, use:
-
standardized_mean_change(aliases:smc,pre_post_smd,repeated_measures_smd)
The diagonal uses sample size, the effect size, and the pre-post
correlation. When an outcome-correlation column such as
r2do or rho is supplied, rows with the same
sample_id receive an approximate off-diagonal
covariance.
smc_dat <- data.frame(
study = c("s1", "s1", "s2", "s2"),
sample_id = c("a", "a", "b", "b"),
yi = c(0.35, 0.42, 0.22, 0.31),
n = c(40, 40, 35, 35),
r_pre_post = c(0.60, 0.60, 0.55, 0.55),
r2do = c(0.50, 0.50, 0.45, 0.45)
)
S_smc <- mars:::within_varcov(
data = smc_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "standardized_mean_change"
)
S_smc[[1]]
#> [,1] [,2]
#> [1,] 0.02153125 0.01093277
#> [2,] 0.01093277 0.0222050010. Incidence Rates and Survival Summaries
For Poisson-style event rates with person-time denominators, use:
-
log_rate_ratio(aliases:rate_ratio,incidence_rate_ratio) -
rate_difference(alias:incidence_rate_difference)
For log hazard ratios, use:
-
log_hr(aliases:hr,hazard_ratio)
The log-hazard-ratio path is diagonal and requires an explicit variance or standard-error column, because shared-arm survival covariances cannot generally be recovered from a published log HR alone.
rate_dat <- data.frame(
study = c("s1", "s1", "s2", "s2"),
control_id = c("c1", "c1", "c2", "c2"),
event_t = c(18, 21, 12, 14),
event_c = c(15, 15, 10, 10),
person_time_t = c(120, 130, 100, 105),
person_time_c = c(140, 140, 95, 95)
)
rate_dat$yi <- log((rate_dat$event_t / rate_dat$person_time_t) /
(rate_dat$event_c / rate_dat$person_time_c))
S_rate_ratio <- mars:::within_varcov(
data = rate_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "log_rate_ratio"
)
hr_dat <- data.frame(
study = c("s1", "s1", "s2"),
yi = c(log(0.80), log(1.10), log(0.95)),
sei = c(0.12, 0.15, 0.18)
)
S_hr <- mars:::within_varcov(
data = hr_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "log_hr"
)
S_rate_ratio[[1]]
#> [,1] [,2]
#> [1,] 0.12222222 0.06666667
#> [2,] 0.06666667 0.11428571
S_hr[[1]]
#> [,1] [,2]
#> [1,] 0.0144 0.0000
#> [2,] 0.0000 0.022511. Transformed Proportions
For transformed single-arm proportions, use:
-
logit_proportion(alias:logit_prop) -
arcsine_proportion(alias:arcsine_prop) -
freeman_tukey_proportion(aliases:freeman_tukey_prop,pft)
S_logit_prop <- mars:::within_varcov(
data = prop_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "logit_proportion"
)
S_arcsine_prop <- mars:::within_varcov(
data = prop_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "arcsine_proportion"
)
S_ft_prop <- mars:::within_varcov(
data = prop_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "freeman_tukey_proportion"
)
S_logit_prop[[1]]
#> [,1] [,2]
#> [1,] 0.0931677 0.00000000
#> [2,] 0.0000000 0.07828283
S_arcsine_prop[[1]]
#> [,1] [,2]
#> [1,] 0.004166667 0.000000000
#> [2,] 0.000000000 0.004032258
S_ft_prop[[1]]
#> [,1] [,2]
#> [1,] 0.004132231 0.000
#> [2,] 0.000000000 0.00412. Partial Correlations, Fisher z, and Reliability
Correlation-matrix workflows can also use Fisher-z transformed correlations:
-
fisher_z_simple,fisher_z_weighted,fisher_z_average
The function converts z values back to correlations for the Olkin-Siotani calculation, then applies a delta-method transformation back to the z scale.
Partial correlations and reliability coefficients use diagonal approximations:
-
partial_cor(aliases:partial_correlation,partial_r) -
partial_fisher_z(alias:partial_z) -
reliability(aliases:cronbach_alpha,alpha) log_reliability
pc_dat <- data.frame(
study = c("s1", "s1", "s2"),
yi = c(0.20, 0.30, 0.18),
n = c(80, 82, 75),
p = c(3, 3, 2)
)
S_partial <- mars:::within_varcov(
data = pc_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "partial_cor"
)
rel_dat <- data.frame(
study = c("s1", "s1", "s2"),
alpha = c(0.82, 0.78, 0.85),
n = c(100, 95, 110),
items = c(8, 7, 9)
)
S_reliability <- mars:::within_varcov(
data = rel_dat,
N = NULL,
effect_name = "alpha",
study = "study",
type = "reliability"
)
S_partial[[1]]
#> [,1] [,2]
#> [1,] 0.01245405 0.00000000
#> [2,] 0.00000000 0.01089605
S_reliability[[1]]
#> [,1] [,2]
#> [1,] 0.0007556851 0.000000000
#> [2,] 0.0000000000 0.00121433713. Generic Diagonal Options
For purely diagonal within-study structures:
-
univariate(vector per study, for univariate analysis) -
multilevel(diagonal matrix per study)
diag_dat <- data.frame(
study = c("s1", "s1", "s2"),
vi = c(0.04, 0.05, 0.03)
)
S_uni <- mars:::within_varcov(
data = diag_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "univariate",
variance = "vi"
)
S_ml <- mars:::within_varcov(
data = diag_dat,
N = NULL,
effect_name = "yi",
study = "study",
type = "multilevel",
variance = "vi"
)
S_uni[[1]]
#> [1] 0.04 0.05
S_ml[[1]]
#> [,1] [,2]
#> [1,] 0.04 0.00
#> [2,] 0.00 0.05These same varcov_type values can be passed to
mars() / estimation() for multivariate
analyses.
Method References
The covariance structures follow large-sample approximations for dependent effect sizes and common meta-analytic effect-size transformations. General dependent-effect-size formulas are anchored by Gleser and Olkin (2009) and Viechtbauer (2010). Correlation-matrix covariances use Olkin and Siotani (1976). Standardized mean differences and standardized mean change draw on Hedges and Olkin (1985), Becker (1988), and Morris (2008). Continuous response ratios draw on Lajeunesse (2011) and Friedrich, Adhikari, and Beyene (2011). Survival summaries draw on Parmar, Torri, and Stewart (1998) and Tierney et al. (2007). Transformed proportions draw on Freeman and Tukey (1950) and Barendregt et al. (2013). Reliability-coefficient approximations draw on Cronbach (1951) and Bonett (2002). Partial-correlation support is aligned with Aloe and Thompson (2013) and Aloe et al. (2016).