mediation_free.RmdThe jamovi module pamlj offers three ways to set up a
mediation power analysis: the simple model (3
variables), the complex templates (two/three parallel
mediators, serial mediation) and the free interface,
which lets you describe any recursive mediation model by typing
its equations in a model syntax. This vignette shows how to use the free
interface from R, via pamlj::pamlmed() with
mode = "medmodels".
The free interface is useful when your model does not match one of
the predefined templates: several independent variables, an arbitrary
number of mediators, serial and parallel pathways combined, and so on.
From the equations, pamlj builds the path model, finds
every indirect (mediated) effect, and computes the power parameters for
each of them.
In R, the model is passed as a single string to the code
argument (one equation per line, separated by \n). Every
other argument — aim, n, power,
test, sig.level, … — works as in the other
mediation modes. The results table is returned in
obj$powertab$asDF.
The model is described with one regression equation per
endogenous variable (every variable that is predicted by
others), written in the familiar lm()/lavaan
style. The classical simple mediation reads:
res <- pamlj::pamlmed(
mode = "medmodels",
code = "m ~ .3*x
y ~ .2*x + .4*m",
aim = "n",
power = .80,
test = "joint"
)
#>
#> Joint-significance power is computed from the distribution of each path coefficient.
res$powertab$asDF
#> effect n a b cprime es power sig.level
#> 1 x → m → y 87 0.3 0.4 0.2 0.12 0.8 0.05Each line reads as outcome ~ predictors. Here
x predicts the mediator m with a standardized
coefficient of .3, and y is predicted by both
x (direct effect c' = .2) and m
(b = .4). The mediated effect x → m → y is the
product of the path coefficients, .3 * .4 = .12 (the
es / ME column), and the table reports the
sample size required to detect it with power .80.
A few rules apply to the syntax:
value*variable (e.g. .4*m). Coefficients
are completely standardized path coefficients and their absolute value
must lie between .001 and .99.1) are ignored and interaction
(x:z) or categorical ([...]) terms are not
allowed.pamlj automatically enumerates every indirect effect in
the model — each simple directed path of at least two edges that runs
from an exogenous variable (a source, never predicted by
others) to a final outcome (a sink, that predicts nothing).
Each such effect becomes one row of the results table, labelled with its
path in the effect column.
A model with two parallel mediators therefore yields two indirect effects:
res <- pamlj::pamlmed(
mode = "medmodels",
code = "m1 ~ .4*x
m2 ~ .5*x
y ~ .1*x + .2*m1 + .3*m2",
aim = "power",
n = 200,
test = "joint"
)
#>
#> Joint-significance power is computed from the distribution of each path coefficient.
res$powertab$asDF[, c("effect", "a", "b", "es", "power")]
#> effect a b es power
#> 1 x → m1 → y 0.4 0.2 0.08 0.8193946
#> 2 x → m2 → y 0.5 0.3 0.15 0.9826651For every indirect effect the table reports the first path
coefficient (a), the remainder of the product
(b), the mediated effect size es
(ME, the product of all coefficients along the path) and
the requested quantity (here the power at
n = 200).
The power of each indirect effect depends on the test selected. With the joint significance test (Yzerbyt et al., 2018), two effects that share their weakest path can require the same sample size even when their other coefficients differ, because the shared (weaker) coefficient drives the power.
Variables can be correlated with the cor() directive,
written on its own line. The most common use is two parallel
mediators whose residuals are correlated:
res <- pamlj::pamlmed(
mode = "medmodels",
code = "m1 ~ .4*x
m2 ~ .5*x
y ~ .1*x + .2*m1 + .3*m2
cor(m1,m2) = .3",
aim = "power",
n = 200,
test = "joint",
inspect_cors = TRUE
)
#>
#> Joint-significance power is computed from the distribution of each path coefficient.
res$powertab$asDF[, c("effect", "es", "power")]
#> effect es power
#> 1 x → m1 → y 0.08 0.7771818
#> 2 x → m2 → y 0.15 0.9712231cor(m1,m2) = .3 sets the correlation between
m1 and m2 to .3, following the
lavaan convention m1 ~~ .3*m2. The separator
can be either : or =, so
cor(m1,m2):.3 is equivalent. Several cor()
lines can be specified. If the requested correlations imply an
impossible (non positive-definite) covariance matrix, the function
reports it.
Setting inspect_cors = TRUE adds a table of the
model-implied correlations among all variables, which is handy to check
what actually entered the model:
res$implied_cors$asDF
#> variable x m1 m2 y
#> 1 x 1.00 0.40 0.50 0.33
#> 2 m1 0.40 1.00 0.50 0.39
#> 3 m2 0.50 0.50 1.00 0.45
#> 4 y 0.33 0.39 0.45 1.00When aim = "es", pamlj solves for the
minimum detectable effect (MDE): given a fixed sample
size and the desired power, it finds the smallest indirect effect the
design can detect. Because a mediated effect is a product of
path coefficients, the answer depends on which coefficient is
allowed to change while the others stay fixed.
By default, pamlj works on each indirect effect
separately and resizes its first edge (the path leaving
the independent variable, the a path). This needs no extra
input — just set aim = "es":
res <- pamlj::pamlmed(
mode = "medmodels",
code = "m1 ~ .4*x
m2 ~ .5*x
y ~ .1*x + .2*m1 + .3*m2",
aim = "es",
n = 250,
power = .80,
test = "joint"
)
#>
#> Joint-significance power is computed from the distribution of each path coefficient.
res$powertab$asDF[, c("effect", "a", "b", "es", "power")]
#> effect a b es power
#> 1 x → m1 → y 0.1913634 0.2 0.03827269 0.8
#> 2 x → m2 → y 0.1759490 0.3 0.05278470 0.8To target a specific coefficient instead — for instance the
b path of a mediator, or a coefficient shared by several
indirect effects — give it a symbolic label in the
syntax and select it with the test: directive. A label is a
letter placed before the value, written
label*value*variable:
res <- pamlj::pamlmed(
mode = "medmodels",
code = "m1 ~ .4*x
m2 ~ .5*x
y ~ .1*x + a*.2*m1 + .3*m2
test: a",
aim = "es",
n = 250,
power = .80,
test = "joint"
)
#>
#> Joint-significance power is computed from the distribution of each path coefficient.
res$powertab$asDF[, c("effect", "a", "b", "es", "power")]
#> effect a b es power
#> 1 x → m1 → y 0.4 0.1754476 0.07017906 0.7999768
#> 2 x → m2 → y 0.5 0.3000000 0.15000000 0.9948623Here the coefficient of m1 → y is labelled
a, and test: a (equivalently
test = a) tells pamlj to find the minimum
detectable effect by resizing that coefficient. If the label is
not defined, or the labelled coefficient is not part of any indirect
effect, the analysis falls back to the per-effect default.
pamlj resizes the selected coefficient — keeping every
other coefficient at its specified value — until the power of the
indirect effect(s) that travel through that coefficient reaches
the desired level. When the coefficient lies on more than one indirect
path (a shared edge), the search drives the weakest of
those effects to the target, so that every affected effect reaches
at least the requested power. Effects that do not pass through
the coefficient are left unchanged.
Resizing a single coefficient cannot always reach the requested power. The power of an indirect effect, seen as a function of one of its coefficients, is unimodal: it rises, reaches a peak, then falls back as the coefficient approaches 1 (the mediator becomes collinear with its predictor and the other coefficients’ standard errors explode). The other coefficients on the path therefore cap the achievable power: if the requested power sits above that peak, no value of the single coefficient can deliver it.
When this happens, pamlj switches to a balanced
solution: instead of moving one coefficient, it grows
all the coefficients of the path together to a common value,
which removes the bottleneck and can reach any power below 1. A message
explains what happened, and the solution is recognisable in the table
because the a and b columns of an affected
effect become equal (every edge on the path is set to the same
value):
res <- pamlj::pamlmed(
mode = "medmodels",
code = "m1 ~ .4*x
m2 ~ .5*x
y ~ .1*x + .2*m1 + .3*m2",
aim = "es",
n = 100,
power = .90,
test = "joint"
)
#>
#> Joint-significance power is computed from the distribution of each path coefficient.
res$powertab$asDF[, c("effect", "a", "b", "es", "power")]
#> effect a b es power
#> 1 x → m1 → y 0.3374171 0.3374171 0.1138503 0.9
#> 2 x → m2 → y 0.3453462 0.3453462 0.1192640 0.9If even the balanced solution cannot reach the target at the given sample size, the table reports the largest detectable effect together with the maximum power it yields, and suggests increasing the sample size. In practice the balanced solution is most useful as a feasibility check: when it appears, the chosen sample size is too small for the requested power whatever single coefficient you adjust, and the common value shows how large every path would have to be to make the design work.
The free interface supports the same tests as the other mediation
models, set with the test argument:
"joint" — joint significance (Yzerbyt et al., 2018),
the default and recommended method;"sobel" — the Sobel test (Sobel, 1982);"parametric" / "simulation" — the Monte
Carlo confidence-interval methods (MacKinnon, Lockwood & Williams,
2004). The number of simulations is set with mcR, and
set_seed = TRUE with seed = <n> makes
the result reproducible.
res <- pamlj::pamlmed(
mode = "medmodels",
code = "m1 ~ .4*x
m2 ~ .5*x
y ~ .1*x + .2*m1 + .3*m2",
aim = "power",
n = 200,
test = "sobel"
)
#>
#> Sobel test method is based on power parameters approximation. Please use joint-significance or bootstrap confidence intervals for more accurate results
res$powertab$asDF[, c("effect", "es", "power")]
#> effect es power
#> 1 x → m1 → y 0.08 0.7430981
#> 2 x → m2 → y 0.15 0.9549460Yzerbyt, V., Muller, D., Batailler, C., & Judd, C. M. (2018). New recommendations for testing indirect effects in mediational models: The need to report and test component paths. Journal of Personality and Social Psychology, 115(6), 929–943.
Sobel, M. E. (1982). Asymptotic confidence intervals for indirect effects in structural equation models. Sociological Methodology, 13, 290–312.
MacKinnon, D. P., Lockwood, C. M., & Williams, J. (2004). Confidence limits for the indirect effect: Distribution of the product and resampling methods. Multivariate Behavioral Research, 39(1), 99–128.