*! version 4.03 David Fisher 12oct2022

Title

ipdmetan -- Perform two-stage individual participant data (IPD) meta-analysis

Syntax

Syntax 1: command-based syntax; "generic" effect measure

ipdmetan
[exp_list]
, study(varname [, missing]) [options] : command [if] [in] ...

Syntax 2: collapse-based syntax; "specific" effect measure

ipdmetan
input_varlist [if] [in]
, study(varname [, missing]) [options]

where input_varlist is one of the following:

var_outcome var_treat where var_outcome and var_treat are both binary 0, 1

var_outcome var_treat where var_outcome is continuous and var_treat is binary 0, 1

var_treat where var_treat is binary 0, 1 and the data have previously been stset.

The terms "generic" and "specific" are used to differentiate between derivation of effect sizes and standard errors which could,
in the inverse-variance meta-analysis context, be interpreted generically (although in practice, of course, the interpretation is governed by command);
and the use of collapse to directly convert the IPD to an aggregate dataset with a specific data structure
such as a 2x2 contingency table, or means and SDs by treatment arm.
There is a substantial difference in syntax; in the remainder of the ipdmetan documentation the terms "Syntax 1" and "Syntax 2" will be used.

Main
options any metan options, as appropriate, except npts(varname)

Syntax 1 only
messages print messages relating to success of model fits

interaction automatically identify and pool a treatment-covariate interaction

poolvar(model_coefficient) specify explicitly the coefficient to pool

nototal suppress initial fitting of command to the entire dataset

wgt(exp) user-defined weights

Syntax 2 only
wgt([(stat)] varname) user-defined weights

Syntax 2 with logrank only
strata specify further variables by which to stratify the log-rank calculations

Combined IPD/aggregate data analysis
ad(filename [if] [in], aggregate_data_options)
combine IPD with aggregate data stored in filename

Forest plots
lcols(cols_info) rcols(cols_info)
display (and/or save) columns of additional data

npts display participant numbers in the forest plot

plotid(varname|_BYAD [, list nograph])
define groups of observations in which to apply specific plot rendition options

metan_fplotopts other options pertaining to the forest plot
as described in metan under "Forest plot and/or saved data"

forestplot(forestplot_options) other options as described in forestplot

where model_coefficient is a variable name, a level indicator, an interaction indicator,
or an interaction involving continuous variables (c.f. syntax of test)

and where cols_info has the following syntax, which is based on that of collapse:

[(stat)] [newname=]item [%fmt] ["label"] [[newname=]item [%fmt "label"] ] ... [ [(stat)] ...]

where stat is as defined in collapse;
newname is an optional user-specified variable name;
item is the name of either a numeric returned quantity from command (in parentheses, see exp_list)
or a variable currently in memory; %fmt is an optional format; and "label" is an optional variable label.

aggregate_data_options

vars(varlist) variables containing effect size and either standard error or 95% confidence limits, on the normal scale

npts(varname) variable containing participant numbers

byad IPD and aggregate data are to be treated as subgroups (rather than as a single set of estimates)

logrank specify that vars() are to be interpreted as O-E and V

relabel force relabelling of studies within the combined IPD/aggregate dataset

Description

ipdmetan performs two-stage individual participant-data (IPD) meta-analysis. There are two basic syntaxes, as shown above.

Syntax 1 fits the model command once within each level of study_ID
and saves effect sizes and standard errors. By default these are pooled using inverse-variance, with output displayed on screen and in a forest plot.
Any e-class regression command (whether built-in or user-defined) should be compatible with this syntax of ipdmetan.
Some prefix commands are also valid; see below.

In the case of non e-class commands - those which do not change the contents of e(b) -,
the effect size and standard error statistics to be collected from the execution of command
must be specified manually by supplying exp_list.
If command changes the contents in e(b), exp_list defaults to
_b[varname] _se[varname],
where varname is the first independent variable within command.

The following prefix commands are valid with ipdmetan: bootstrap; jackknife; svy; mi estimate, post; bayes; version.

Syntax 2 converts the IPD to aggregate data using collapse;
after which any of the analysis methods used by metan,
such as Mantel-Haenszel and Standardised Weighted Means, become applicable.

There are three ways in which ipdmetan Syntax 2 can convert IPD to aggregate data, as listed under Syntax.
In the first case (binary outcome; binary treatment variable), the data will be summarised by study as cell counts from a 2x2 contingency table.
In the second case (continuous outcome; binary treatment variable), the data will be summarised by study as means and SDs by treatment arm.
Finally, if a binary treatment variable alone is supplied and the data is stset,
the survival data will be summarised by study using Peto logrank O-E and V statistics
(note that this supersedes petometan which previously formed part of the ipdmetan package).

Note that with Syntax 2, the effect measure must be made explicit by use of an option such as rr, or, hr, smd or logrank;
see metan and eform_option.

This version of ipdmetan requires version 4.0+ of the package metan to be installed.
This package is available from the SSC archive; type ssc describe metan.

Options

Main

study(study_ID [, missing]) (required) specifies the variable containing the study identifier,
which must be either integer-valued or string.

missing requests that missing values be treated as potential study identifiers; the default is to exclude them.

interaction (Syntax 1 only) indicates that command contains one or more interaction effects
supplied using factor-variable syntax (see fvvarlist),
and that the first valid interaction effect should be pooled across studies.
This is intended as a helpful shortcut for performing two-stage "deft" interaction analyses as described in Fisher 2017.
However, it is not foolproof, and the identified coefficient should be checked carefully.
Alternatively, the desired coefficient to be pooled may be supplied directly using poolvar().

Note that forestplot(interaction [...] ) works slightly differently.
Valid with both Syntax 1 and Syntax 2, this option requests that forestplot apply the set of plot-related options appropriate for interactions;
that is, using circles in place of squares and diamonds.
This may be useful in situations where the pooled effect is to be interpreted as an interaction,
but command is not formulated such that a standard interaction coefficient is present (or if poolvar() is used; see above).

interaction implies forestplot(interaction [...] ); there is no need to specify interaction twice.

messages (Syntax 1 only) requests that information is printed to screen regarding whether effect size and standard error statistics
have been successfully obtained from each study, and (if applicable) whether the iterative random-effects calculations
converged successfully.

nototal (Syntax 1 only) requests that command not be fitted within the entire dataset, e.g. for time-saving reasons.
By default, such fitting is done to check for problems in convergence and in the validity of requested coefficients and
returned expressions. If nototal is specified, either poolvar() or exp_list must be supplied,
and a message appears above the table of results warning that estimates should be double-checked by the user.

poolvar(model_coefficient) (Syntax 1 only) allows the coefficient to be pooled to be explicitly stated in situations where it may not be obvious,
or where ipdmetan has made a previous incorrect assumption. model_coefficient should be a variable name,
a level indicator, an interaction indicator, or an interaction involving continuous variables (c.f. syntax of test).
To use equations, use the format poolvar(eqname:varname).

strata(varlist) (Syntax 2 with logrank only) specifies further variables to be used in log-rank calculations
but not be presented in the output.

wgt() specifies user-defined weights. With Syntax 1, wgt() expects an expression involving returned statistics.
For example, to weight on the number of observations, you might specify wgt(e(N)).
With Syntax 2, wgt() expects a collapse-based syntax.
Hence, again, to weight on the number of observations, you might specify wgt((sum) cons) where cons is a variable containing 1 for all observations. You should only use this option if you are satisfied that the weights are meaningful.

Note that the scale of user-defined weights is immaterial, since individual weights are normalised.
Hence, if saving() option is used, an analysis may be recreated from within the saved dataset
using the option wgt(_WT).

Combined IPD/aggregate data analysis

ad([filename] [if] [in], aggregate_data_options)
allows aggregate (summary) data may be included in the analysis alongside IPD, for example if some studies do not have IPD available.

aggregate_data_options are as follows:

vars(varlist) contains the names of variables containing the effect size
and either a standard error or lower and upper 95% confidence limits, on the linear scale.
If filename is supplied, varlist will be taken from within the external file;
otherwise varlist will be taken from the data currently in memory.
If confidence limits are supplied, they must be derived from a Normal distribution or the pooled result will not be accurate (see metan).

npts(varname) allows participant numbers stored in varname within filename to be displayed in tables and forest plots.

byad specifies that aggregate data and IPD respectively are to be treated as subgroups.

logrank specifies that vars(varlist) contains the statistics O-E and V
rather than the default ES and seES.

relabel tells ipdmetan to re-label all studies sequentially as "1", "2", etc.,
(copying value labels across, if found) in the event that value labels do not agree between IPD and aggregate datasets.

Note that subgroups in aggregate data may be analysed in the same way as for IPD - that is, with the by(varname) option to ipdmetan.
varname may be found in either the data in memory (IPD), or in the aggregate dataset, or both.

Forest plots

lcols(cols_info), rcols(cols_info)
define columns of additional summary data to be presented to the left or right of the forest plot.
With metan these options simply require a varlist, but in the IPD context the syntax is more complicated.
The user may specify summary statistics by which to collapse the data,
as well as characteristics of the summarised variables such as name, title and format which will be carried over to the forest plot.

Specifying newname is only necessary in circumstances where the name of the variable is important
in the dataset underlying the forest plot (i.e. the dataset created by saving() if applicable).
For example, you may have an aggregate dataset with a variable containing data equivalent to an item,
and wish for all such data (whether IPD or aggregate) to appear in a single column in the forest plot.
To achieve this, specify newname as the name of the relevant variable in the aggregate dataset.
Make sure that the variables in the IPD and aggregate datasets do not have conflicting data_types (e.g. string vs numeric)
or a merge error will be returned.

If item is an existing string variable, the first non-empty observation for each study will be used,
and item will not be displayed alongside overall or subgroup pooled estimates.
(This behaviour may also be forced upon a numeric variable by first converting it into a string using recode or tostring.)

Formatting of forest plot columns may be controlled using cols_info.
Note that unlike (stat), %fmt only applies to each immediately preceding item.
By default, Stata displays strings as right-justified.
A single string-valued forest plot column may be left-justified as described in format.
To left-justify all strings in the forest plot, the forestplot_option leftjustify has been provided.

(Note that the syntax of lcols() and rcols() with metan and forestplot is as a list of existing variable names only.)

npts requests that participant numbers be displayed in a column to the left of the forest plot.
This is effectively shorthand for lcols(cols_info_defining_participant_numbers).

plotid(varname|_BYAD [, list nograph]) is really a forestplot option, but has a slightly
extended syntax when supplied to ipdmetan. varname may be replaced with _BYAD if the byad suboption
is supplied to ad, since in this case the subgrouping is not defined by an existing variable.

For further details of this option and the list and nograph suboptions, see forestplot.

Saved results

ipdmetan saves the same results in r() as metan, with the following additions:

Macros

r(command) Full estimation command-line

r(cmdname) Estimation command name

r(estexp) Name of pooled coefficient

Matrices

r(coeffs) Matrix of study and subgroup identifiers, effect coefficients, numbers of participants, and weights

Variables

_rsample Observations included in the analysis (c.f. e(sample))

N.B. For obvious reasons, new variables _ES, _seES etc. are not added to the data with ipdmetan.
They are instead returned within the matrix r(coeffs).

Examples

Setup

. use "http://fmwww.bc.edu/repec/bocode/i/ipdmetan_example.dta", clear

. stset tcens, fail(fail)

(click to run)

Basic use

. ipdmetan, study(trialid) hr by(region) nograph : stcox trt, strata(sex)

Use of plotid()

. ipdmetan, study(trialid) hr by(region) plotid(region)

forest(favours(Favours treatment # Favours control) box1opts(mcolor(red)) ci1opts(lcolor(red) rcap)box2opts(mcolor(blue)) ci2opts(lcolor(blue)))

: stcox trt, strata(sex)

(click to run)

Treatment-covariate interactions

. ipdmetan, study(trialid) interaction hr keepall

forest(boxsca(200) fp(3)

favours("Favours greater treatment effect" "with higher disease stage"# "Favours greater treatment effect" "with lower disease stage"))

: stcox trt##c.stage

(click to run)

Aggregate data setup: create aggregate dataset from IPD dataset (for example purposes only)

. qui ipdmetan, study(trialid) hr nograph saving(region2.dta) : stcox trt if region==2, strata(sex)

. clonevar _STUDY = trialid

(click to run)

Including aggregate data in the analysis

. ipdmetan, study(_STUDY) hr ad(region2.dta if _USE==1, vars(_ES _seES) npts(_NN) byad) nooverall

: stcox trt if region==1, strata(sex)

(click to run)

Use of non e-class commands and lcols(): Peto log-rank analysis

. ipdmetan (u[1,1]/V[1,1]) (1/sqrt(V[1,1])), study(trialid) by(region) eform effect(Haz. Ratio)

lcols((u[1,1]) %5.2f "o-E(o)" (V[1,1]) %5.2f "V(o)")

forest(nostats nowt favours(Favours treatment # Favours control))

: sts test trt, mat(u V)

(click to run)

However, that was just to demonstrate Syntax 1 with a non e-class command.
The example is a Peto logrank survival analysis, which is much more straightforward using Syntax 2 and the oev option:

. ipdmetan trt, study(trialid) hr oev by(region)

forest(nostats nowt favours(Favours treatment # Favours control))

(click to run)

Author

David Fisher, MRC Clinical Trials Unit at UCL, London, UK.

Email d.fisher@ucl.ac.uk

Acknowledgments

Thanks to Phil Jones at UWO, Canada for suggesting improvements in functionality.

The "click to run" element of the examples in this document is handled using an idea originally developed by Robert Picard.

References

Fisher DJ. 2015. Two-stage individual participant data meta-analysis and generalised forest plots.
Stata Journal 15: 369-96

Fisher DJ, Carpenter JR, Morris TP, Freeman SC, Tierney JF. 2017.
Meta-analytical methods to identify who benefits most from treatments: daft, deluded, or deft approach?
BMJ 356: j573