Nothing
#' Network meta-analysis of binary outcome data
#'
#' @description
#' Provides three models for the network meta-analysis of binary data
#' (Mantel-Haenszel method, based on the non-central hypergeometric
#' distribution, and the inverse variance method).
#'
#' @param event1 Number of events (first treatment).
#' @param n1 Number of observations (first treatment).
#' @param event2 Number of events (second treatment).
#' @param n2 Number of observations (second treatment)
#' @param treat1 Label/Number for first treatment.
#' @param treat2 Label/Number for second treatment.
#' @param studlab An optional - but important! - vector with study
#' labels (see Details).
#' @param data An optional data frame containing the study
#' information.
#' @param subset An optional vector specifying a subset of studies to
#' be used.
#' @param sm A character string indicating underlying summary measure,
#' i.e., \code{"RD"}, \code{"RR"}, \code{"OR"}, \code{"ASD"}.
#' @param method A character string indicating which method is to be
#' used for pooling of studies. One of \code{"Inverse"},
#' \code{"MH"}, or \code{"NCH"}, can be abbreviated.
#' @param cc.pooled A logical indicating whether \code{incr} should be
#' used as a continuity correction, when calculating the network
#' meta-analysis estimates.
#' @param incr A numerical value which is added to each cell count,
#' i.e., to the numbers of events and non-events, of all treatment
#' arms in studies with zero events or non-events in any of the
#' treatment arms ("continuity correction").
#' @param allincr A logical indicating whether \code{incr} should be
#' added to each cell count of all studies if a continuity
#' correction was used for at least one study (only considered if
#' \code{method = "Inverse"}). If FALSE (default), \code{incr} is
#' used as continuity correction only for studies with zero events
#' or zero non-events in any of the treatment arms.
#' @param addincr A logical indicating whether \code{incr} should be
#' added to each cell count of all studies, irrespective of zero
#' cell counts (only considered if \code{method = "Inverse"}).
#' @param allstudies A logical indicating whether studies with zero
#' events or non-events in all treatment arms should be included in
#' an inverse variance meta-analysis (applies only if \code{method =
#' "Inverse"} and \code{sm} is equal to either \code{"RR"} or
#' \code{"OR"}).
#' @param level The level used to calculate confidence intervals for
#' individual studies.
#' @param level.ma The level used to calculate confidence intervals
#' for network estimates.
#' @param common A logical indicating whether a common effects network
#' meta-analysis should be conducted.
#' @param random A logical indicating whether a random effects network
#' meta-analysis should be conducted.
#' @param prediction A logical indicating whether a prediction
#' interval should be printed (only considered if \code{method =
#' "Inverse"}).
#' @param level.predict The level used to calculate prediction
#' interval for a new study (only considered if \code{method =
#' "Inverse"}).
#' @param reference.group Reference treatment.
#' @param baseline.reference A logical indicating whether results
#' should be expressed as comparisons of other treatments versus the
#' reference treatment (default) or vice versa. This argument is
#' only considered if \code{reference.group} has been specified.
#' @param all.treatments A logical or \code{"NULL"}. If \code{TRUE},
#' matrices with all treatment effects, and confidence limits will
#' be printed.
#' @param seq A character or numerical vector specifying the sequence
#' of treatments in printouts.
#' @param tau.preset An optional value for manually setting the
#' square-root of the between-study variance \eqn{\tau^2} (only
#' considered if \code{method = "Inverse"}).
#' @param tol.multiarm A numeric for the tolerance for consistency of
#' treatment estimates in multi-arm studies which are consistent by
#' design (only considered if \code{method = "Inverse"}).
#' @param tol.multiarm.se A numeric for the tolerance for consistency
#' of standard errors in multi-arm studies which are consistent by
#' design (only considered if the argument is not \code{NULL} and
#' \code{method = "Inverse"}).
#' @param details.chkmultiarm A logical indicating whether treatment
#' estimates and / or variances of multi-arm studies with
#' inconsistent results or negative multi-arm variances should be
#' printed (only considered if \code{method = "Inverse"}).
#' @param details.chkdata A logical indicating whether number of
#' events and participants of studies with inconsistent data should
#' be printed.
#' @param sep.trts A character used in comparison names as separator
#' between treatment labels.
#' @param nchar.trts A numeric defining the minimum number of
#' characters used to create unique treatment names (see Details).
#' @param func.inverse R function used to calculate the pseudoinverse
#' of the Laplacian matrix L (see \code{\link{netmeta}}).
#' @param backtransf A logical indicating whether results should be
#' back transformed in printouts and forest plots. If
#' \code{backtransf = TRUE}, results for \code{sm = "OR"} are
#' presented as odds ratios rather than log odds ratios, for
#' example.
#' @param title Title of meta-analysis / systematic review.
#' @param keepdata A logical indicating whether original data (set)
#' should be kept in netmeta object.
#' @param warn A logical indicating whether warnings should be printed
#' (e.g., if studies are excluded from meta-analysis due to zero
#' standard errors).
#' @param warn.deprecated A logical indicating whether warnings should
#' be printed if deprecated arguments are used.
#' @param \dots Additional arguments (to catch deprecated arguments).
#'
#' @details
#' This function implements three models for the network meta-analysis
#' of binary data:
#' \itemize{
#' \item The Mantel-Haenszel network meta-analysis model, as described
#' in Efthimiou et al. (2019) (\code{method = "MH"});
#' \item a network meta-analysis model using the non-central
#' hypergeometric distribution with the Breslow approximation, as
#' described in Stijnen et al. (2010) (\code{method = "NCH"});
#' \item the inverse variance method for network meta-analysis
#' (\code{method = "Inverse"}), also provided by
#' \code{\link{netmeta}}.
#' }
#'
#' Comparisons belonging to multi-arm studies are identified by
#' identical study labels (argument \code{studlab}). It is therefore
#' important to use identical study labels for all comparisons
#' belonging to the same multi-arm study.
#'
#' Data entry for this function is in \emph{contrast-based} format,
#' that is, each line of the data corresponds to a single pairwise
#' comparison between two treatments (arguments \code{treat1},
#' \code{treat2}, \code{event1}, \code{n1}, \code{event2}, and
#' \code{n2}). If data are provided in \emph{arm-based} format, that
#' is, number of events and participants are given for each treatment
#' arm separately, function \code{\link{pairwise}} can be used to
#' transform the data to \emph{contrast-based} format (see help page
#' of function \code{\link{pairwise}}).
#'
#' Note, all pairwise comparisons must be provided for a multi-arm
#' study. Consider a multi-arm study of \emph{p} treatments with known
#' variances. For this study, the number of events and observations
#' must be provided for each treatment, for each of \emph{p}(\emph{p}
#' - 1) / 2 possible comparisons in separate lines in the data. For
#' instance, a three-arm study contributes three pairwise comparisons,
#' a four-arm study even six pairwise comparisons. Function
#' \code{\link{pairwise}} automatically calculates all pairwise
#' comparisons for multi-arm studies.
#'
#' For \code{method = "Inverse"}, both common and random effects
#' models are calculated regardless of values choosen for arguments
#' \code{common} and \code{random}. Accordingly, the network estimates
#' for the random effects model can be extracted from component
#' \code{TE.random} of an object of class \code{"netmeta"} even if
#' argument \code{random = FALSE}. However, all functions in R
#' package \bold{netmeta} will adequately consider the values for
#' \code{common} and \code{random}. E.g. function
#' \code{\link{print.summary.netmeta}} will not print results for the
#' random effects model if \code{random = FALSE}.
#'
#' For the random-effects model, the direct treatment estimates are
#' based on the common between-study variance \eqn{\tau^2} from the
#' network meta-analysis.
#'
#' For \code{method = "MH"} and \code{method = "NCH"}, only a common
#' effects model is available.
#'
#' By default, treatment names are not abbreviated in
#' printouts. However, in order to get more concise printouts,
#' argument \code{nchar.trts} can be used to define the minimum number
#' of characters for abbreviated treatment names (see
#' \code{\link{abbreviate}}, argument \code{minlength}). R function
#' \code{\link{treats}} is utilised internally to create abbreviated
#' treatment names.
#'
#' Names of treatment comparisons are created by concatenating
#' treatment labels of pairwise comparisons using \code{sep.trts} as
#' separator (see \code{\link{paste}}). These comparison names are
#' used in the covariance matrices \code{Cov.common} and
#' \code{Cov.random} and in some R functions, e.g,
#' \code{\link{decomp.design}}. By default, a colon is used as the
#' separator. If any treatment label contains a colon the following
#' characters are used as separator (in consecutive order):
#' \code{"-"}, \code{"_"}, \code{"/"}, \code{"+"}, \code{"."},
#' \code{"|"}, and \code{"*"}. If all of these characters are used in
#' treatment labels, a corresponding error message is printed asking
#' the user to specify a different separator.
#'
#' @return
#' An object of class \code{netmetabin} and \code{netmeta} with
#' corresponding \code{print}, \code{summary}, \code{forest}, and
#' \code{netrank} functions. The object is a list containing the
#' following components:
#' \item{studlab, treat1, treat2}{As defined above.}
#' \item{n1, n2, event1, event2}{As defined above.}
#' \item{TE}{Estimate of treatment effect, i.e. difference between
#' first and second treatment (e.g. log odds ratio).}
#' \item{seTE}{Standard error of treatment estimate.}
#' \item{k}{Total number of studies.}
#' \item{m}{Total number of pairwise comparisons.}
#' \item{n}{Total number of treatments.}
#' \item{d}{Total number of designs (corresponding to the unique set
#' of treatments compared within studies).}
#' \item{trts}{Treatments included in network meta-analysis.}
#' \item{k.trts}{Number of studies evaluating a treatment.}
#' \item{n.trts}{Number of observations receiving a treatment.}
#' \item{events.trts}{Number of events observed for a treatment.}
#' \item{studies}{Study labels coerced into a factor with its levels
#' sorted alphabetically.}
#' \item{narms}{Number of arms for each study.}
#' \item{designs}{Unique list of designs present in the network. A
#' design corresponds to the set of treatments compared within a
#' study.}
#' \item{TE.common, seTE.common}{\emph{n}x\emph{n} matrix with estimated
#' overall treatment effects and standard errors for common effects
#' model.}
#' \item{lower.common, upper.common}{\emph{n}x\emph{n} matrices with
#' lower and upper confidence interval limits for common effects
#' model.}
#' \item{statistic.common, pval.common}{\emph{n}x\emph{n} matrices with
#' z-value and p-value for test of overall treatment effect under
#' common effects model.}
#' \item{TE.random, seTE.random}{\emph{n}x\emph{n} matrix with
#' estimated overall treatment effects and standard errors for
#' random effects model (only available if \code{method =
#' "Inverse"}).}
#' \item{lower.random, upper.random}{\emph{n}x\emph{n} matrices with
#' lower and upper confidence interval limits for random effects
#' model (only available if \code{method = "Inverse"}).}
#' \item{statistic.random, pval.random}{\emph{n}x\emph{n} matrices
#' with z-value and p-value for test of overall treatment effect
#' under random effects model (only available if \code{method =
#' "Inverse"}).}
#' \item{TE.direct.common, seTE.direct.common}{\emph{n}x\emph{n} matrix
#' with estimated treatment effects and standard errors from direct
#' evidence under common effects model.}
#' \item{lower.direct.common, upper.direct.common}{\emph{n}x\emph{n}
#' matrices with lower and upper confidence interval limits from
#' direct evidence under common effects model.}
#' \item{statistic.direct.common, pval.direct.common}{\emph{n}x\emph{n}
#' matrices with z-value and p-value for test of overall treatment
#' effect from direct evidence under common effects model.}
#' \item{TE.direct.random, seTE.direct.random}{\emph{n}x\emph{n}
#' matrix with estimated treatment effects and standard errors from
#' direct evidence under random effects model (only available if
#' \code{method = "Inverse"}).}
#' \item{lower.direct.random, upper.direct.random}{\emph{n}x\emph{n}
#' matrices with lower and upper confidence interval limits from
#' direct evidence under random effects model (only available if
#' \code{method = "Inverse"}).}
#' \item{statistic.direct.random,
#' pval.direct.random}{\emph{n}x\emph{n} matrices with z-value and
#' p-value for test of overall treatment effect from direct evidence
#' under random effects model (only available if \code{method =
#' "Inverse"}).}
#' \item{Q}{Overall heterogeneity / inconsistency statistic. (only
#' available if \code{method = "Inverse"})}
#' \item{df.Q}{Degrees of freedom for test of heterogeneity /
#' inconsistency.}
#' \item{pval.Q}{P-value for test of heterogeneity / inconsistency.}
#' \item{I2, lower.I2, upper.I2}{I-squared, lower and upper confidence
#' limits (only available if \code{method = "Inverse"}).}
#' \item{tau}{Square-root of between-study variance (only available if
#' \code{method = "Inverse"}).}
#' \item{Q.heterogeneity}{Overall heterogeneity statistic. (only
#' available if \code{method = "Inverse"})}
#' \item{df.Q.heterogeneity}{Degrees of freedom for test of overall
#' heterogeneity.}
#' \item{pval.Q.heterogeneity}{P-value for test of overall
#' heterogeneity.}
#' \item{Q.inconsistency}{Overall inconsistency statistic.}
#' \item{df.Q.inconsistency}{Degrees of freedom for test of overall
#' inconsistency.}
#' \item{pval.Q.inconsistency}{P-value for test of overall
#' inconsistency.}
#' \item{A.matrix}{Adjacency matrix (\emph{n}x\emph{n}).}
#' \item{H.matrix}{Hat matrix (\emph{m}x\emph{m})}
#' \item{n.matrix}{\emph{n}x\emph{n} matrix with number of
#' observations in direct comparisons.}
#' \item{events.matrix}{\emph{n}x\emph{n} matrix with number of events
#' in direct comparisons.}
#' \item{sm, method, level, level.ma}{As defined above.}
#' \item{incr, allincr, addincr, allstudies, cc.pooled}{As defined
#' above.}
#' \item{common, random}{As defined above.}
#' \item{prediction, level.predict}{As defined above.}
#' \item{reference.group, baseline.reference, all.treatments}{As
#' defined above.}
#' \item{seq, tau.preset, tol.multiarm, tol.multiarm.se}{As defined
#' above.}
#' \item{details.chkmultiarm, details.chkdata}{As defined above.}
#' \item{sep.trts, nchar.trts}{As defined above.}
#' \item{backtransf, title, warn, warn.deprecated}{As defined above.}
#' \item{data}{Data set (in contrast-based format).}
#' \item{data.design}{List with data in arm-based format (each list
#' element corresponds to a single design).}
#' \item{call}{Function call.}
#' \item{version}{Version of R package netmeta used to create object.}
#'
#' @author Orestis Efthimiou \email{oremiou@@gmail.com}, Guido
#' Schwarzer \email{guido.schwarzer@@uniklinik-freiburg.de}
#'
#' @seealso \code{\link{pairwise}}, \code{\link{netmeta}}
#'
#' @references
#' Efthimiou O, Rücker G, Schwarzer G, Higgins J, Egger M, Salanti G
#' (2019):
#' A Mantel-Haenszel model for network meta-analysis of rare events.
#' \emph{Statistics in Medicine},
#' \bold{38}, 2992--3012
#'
#' Senn S, Gavini F, Magrez D, Scheen A (2013):
#' Issues in performing a network meta-analysis.
#' \emph{Statistical Methods in Medical Research},
#' \bold{22}, 169--89
#'
#' Stijnen T, Hamza TH, Ozdemir P (2010):
#' Random effects meta-analysis of event outcome in the framework of
#' the generalized linear mixed model with applications in sparse
#' data.
#' \emph{Statistics in Medicine},
#' \bold{29}, 3046--67
#' @examples
#' data(Dong2013)
#'
#' # Only consider first ten studies (to reduce runtime of example)
#' #
#' first10 <- subset(Dong2013, id <= 10)
#'
#' # Transform data from long arm-based format to contrast-based
#' # format. Argument 'sm' has to be used for odds ratio as summary
#' # measure; by default the risk ratio is used in the metabin
#' # function called internally.
#' #
#' p1 <- pairwise(treatment, death, randomized, studlab = id,
#' data = first10, sm = "OR")
#'
#' # Conduct Mantel-Haenszel network meta-analysis (without continuity
#' # correction)
#' #
#' nb1 <- netmetabin(p1, ref = "plac")
#' nb1
#'
#' # Obtain the league table
#' #
#' netleague(nb1)
#'
#' \dontrun{
#' # Conduct Mantel-Haenszel network meta-analysis for the whole
#' # dataset
#' #
#' p2 <- pairwise(treatment, death, randomized, studlab = id,
#' data = Dong2013, sm = "OR")
#' netmetabin(p2, ref = "plac")
#'
#' # Conduct network meta-analysis using the non-central
#' # hypergeometric model (without continuity correction)
#' #
#' netmetabin(p2, ref = "plac", method = "NCH")
#'
#' # Conduct Mantel-Haenszel network meta-analysis (with continuity
#' # correction of 0.5; include all studies)
#' #
#' netmetabin(p2, ref = "plac", cc.pooled = TRUE)
#'
#' data(Gurusamy2011)
#'
#' p3 <- pairwise(treatment, death, n, studlab = study,
#' data = Gurusamy2011, sm = "OR")
#'
#' # Conduct Mantel-Haenszel network meta-analysis (without continuity
#' # correction)
#' #
#' netmetabin(p3, ref = "cont")
#' }
#'
#' @export netmetabin
netmetabin <- function(event1, n1, event2, n2,
treat1, treat2, studlab,
data = NULL, subset = NULL,
sm,
method = "MH",
cc.pooled = FALSE,
incr, allincr, addincr, allstudies,
level = gs("level"),
level.ma = gs("level.ma"),
common = gs("common"),
random = method == "Inverse" &
(gs("random") | !is.null(tau.preset)),
##
prediction = FALSE,
level.predict = gs("level.predict"),
##
reference.group = "",
baseline.reference = TRUE,
all.treatments = NULL,
seq = NULL,
##
tau.preset = NULL,
##
tol.multiarm = 0.001,
tol.multiarm.se = NULL,
details.chkmultiarm = FALSE,
details.chkdata = TRUE,
##
sep.trts = ":",
nchar.trts = 666,
##
func.inverse = invmat,
##
backtransf = gs("backtransf"),
##
title = "",
keepdata = gs("keepdata"),
warn = TRUE, warn.deprecated = gs("warn.deprecated"),
...) {
##
##
## (1) Check arguments
##
##
modtext <-
paste0("must be equal to 'Inverse' (classic network meta-analysis), ",
"'MH' (Mantel-Haenszel, the default) or ",
"'NCH' (common-effects non-central hypergeometric).")
method <- setchar(method, c("Inverse", "MH", "NCH"), modtext)
chklogical(cc.pooled)
##
chklevel(level)
chklevel(level.predict)
##
chklogical(prediction)
##
## Check for deprecated arguments in '...'
##
args <- list(...)
chklogical(warn.deprecated)
##
level.ma <- deprecated(level.ma, missing(level.ma), args, "level.comb",
warn.deprecated)
chklevel(level.ma)
##
missing.common <- missing(common)
common <- deprecated(common, missing.common, args, "comb.fixed",
warn.deprecated)
common <- deprecated(common, missing.common, args, "fixed",
warn.deprecated)
chklogical(common)
##
random <-
deprecated(random, missing(random), args, "comb.random", warn.deprecated)
chklogical(random)
##
if (method != "Inverse" & !common) {
warning("Argument 'common' set to TRUE for Mantel-Haenszel ",
"method and non-central hypergeometric distribution.",
call. = FALSE)
common <- TRUE
}
##
if (method != "Inverse" & random) {
warning("Argument 'random' set to FALSE for Mantel-Haenszel ",
"method and non-central hypergeometric distribution.",
call. = FALSE)
random <- FALSE
}
##
if (method != "Inverse" & prediction) {
warning("Argument 'prediction' set to FALSE for Mantel-Haenszel ",
"method and non-central hypergeometric distribution.",
call. = FALSE)
prediction <- FALSE
}
##
chklogical(baseline.reference)
##
if (!is.null(all.treatments))
chklogical(all.treatments)
##
if (!is.null(tau.preset))
chknumeric(tau.preset, min = 0, length = 1)
##
chknumeric(tol.multiarm, min = 0, length = 1)
if (!is.null(tol.multiarm.se))
chknumeric(tol.multiarm.se, min = 0, length = 1)
chklogical(details.chkmultiarm)
chklogical(details.chkdata)
##
missing.sep.trts <- missing(sep.trts)
chkchar(sep.trts)
chknumeric(nchar.trts, min = 1, length = 1)
##
chklogical(backtransf)
##
chkchar(title)
chklogical(keepdata)
chklogical(warn)
##
## Check value for reference group
##
if (is.null(all.treatments))
if (reference.group == "")
all.treatments <- TRUE
else
all.treatments <- FALSE
##
chklogical(baseline.reference)
##
missing.incr <- missing(incr)
##
##
## (2) Read data
##
##
nulldata <- is.null(data)
sfsp <- sys.frame(sys.parent())
mc <- match.call()
##
if (nulldata)
data <- sfsp
##
## Catch 'event1', 'event2', 'n1', 'n2', 'treat1', 'treat2', and
## 'studlab' from data:
##
event1 <- catch("event1", mc, data, sfsp)
##
if (is.data.frame(event1) &&
(!is.null(attr(event1, "pairwise")) ||
inherits(event1, "pairwise"))) {
is.pairwise <- TRUE
##
if (missing.incr)
incr <-
replaceNULL(attr(event1, "incr"), gs("incr"))
if (missing(allincr))
allincr <-
replaceNULL(attr(event1, "allincr"), gs("allincr"))
if (missing(addincr))
addincr <-
replaceNULL(attr(event1, "addincr"), gs("addincr"))
if (missing(allstudies))
allstudies <-
replaceNULL(attr(event1, "allstudies"), gs("allstudies"))
##
if (missing(sm) & method == "Inverse")
sm <- replaceNULL(attr(event1, "sm"), gs("smbin"))
else if (method != "Inverse") {
if (!missing(sm) && tolower(sm) != "or")
warning("Argument 'sm' set to 'OR'.", call. = FALSE)
sm <- "OR"
}
##
n1 <- event1$n1
event2 <- event1$event2
n2 <- event1$n2
treat1 <- event1$treat1
treat2 <- event1$treat2
studlab <- event1$studlab
##
pairdata <- event1
data <- event1
##
event1 <- event1$event1
##
chknull(event1, text = "Variable")
chknull(n1, text = "Variable")
chknull(event2, text = "Variable")
chknull(n2, text = "Variable")
chknull(treat1, text = "Variable")
chknull(treat2, text = "Variable")
chknull(studlab, text = "Variable")
}
else {
is.pairwise <- FALSE
##
if (missing.incr)
incr <- gs("incr")
if (missing(allincr))
allincr <- gs("allincr")
if (missing(addincr))
addincr <- gs("addincr")
if (missing(allstudies))
allstudies <- gs("allstudies")
##
if (missing(sm) & method == "Inverse") {
if (!nulldata && !is.null(attr(data, "sm")))
sm <- attr(data, "sm")
else
sm <- ""
}
else if (method != "Inverse") {
if (!missing(sm) && tolower(sm) != "or")
warning("Argument 'sm' set to 'OR'.", call. = FALSE)
sm <- "OR"
}
##
event2 <- catch("event2", mc, data, sfsp)
##
n1 <- catch("n1", mc, data, sfsp)
n2 <- catch("n2", mc, data, sfsp)
##
treat1 <- catch("treat1", mc, data, sfsp)
treat2 <- catch("treat2", mc, data, sfsp)
##
studlab <- catch("studlab", mc, data, sfsp)
##
chknull(event1)
chknull(n1)
chknull(event2)
chknull(n2)
chknull(treat1)
chknull(treat2)
chknull(studlab)
}
##
chknumeric(event1)
chknumeric(n1)
chknumeric(event2)
chknumeric(n2)
##
k.Comp <- length(event1)
##
if (is.factor(treat1))
treat1 <- as.character(treat1)
if (is.factor(treat2))
treat2 <- as.character(treat2)
if (is.factor(studlab))
studlab <- as.character(studlab)
##
## Remove leading and trailing whitespace
##
treat1 <- rmSpace(rmSpace(treat1, end = TRUE))
treat2 <- rmSpace(rmSpace(treat2, end = TRUE))
##
## Keep original order of studies
##
.order <- seq_along(studlab)
##
subset <- catch("subset", mc, data, sfsp)
missing.subset <- is.null(subset)
##
##
## (2b) Store complete dataset in list object data
##
##
if (nulldata & !is.pairwise)
data <- data.frame(.event1 = event1)
else if (nulldata & is.pairwise) {
data <- pairdata
data$.order <- .order
data$.event1 <- event1
}
else
data$.event1 <- event1
##
data$.n1 <- n1
data$.event2 <- event2
data$.n2 <- n2
data$.treat1 <- treat1
data$.treat2 <- treat2
data$.studlab <- studlab
data$.order <- .order
##
if (!missing.subset) {
if (length(subset) == dim(data)[1])
data$.subset <- subset
else {
data$.subset <- FALSE
data$.subset[subset] <- TRUE
}
}
##
chklogical(incr)
chklogical(allincr)
chklogical(addincr)
chklogical(allstudies)
##
m.data <- metabin(event1, n1, event2, n2,
sm = sm, method = "Inverse",
incr = incr, allincr = allincr,
addincr = addincr, allstudies = allstudies,
method.tau = "DL", method.tau.ci = "",
warn = FALSE,
warn.deprecated = FALSE)
##
data$.TE <- m.data$TE
data$.seTE <- m.data$seTE
##
##
## (3) Use subset for analysis
##
##
if (!missing.subset) {
if ((is.logical(subset) & (sum(subset) > k.Comp)) ||
(length(subset) > k.Comp))
stop("Length of subset is larger than number of studies.",
call. = FALSE)
##
studlab <- studlab[subset]
treat1 <- treat1[subset]
treat2 <- treat2[subset]
##
event1 <- event1[subset]
event2 <- event2[subset]
n1 <- n1[subset]
n2 <- n2[subset]
##
.order <- .order[subset]
}
##
## Check for correct treatment order within comparison
##
wo <- treat1 > treat2
##
if (any(wo)) {
tevent1 <- event1
event1[wo] <- event2[wo]
event2[wo] <- tevent1[wo]
##
tn1 <- n1
n1[wo] <- n2[wo]
n2[wo] <- tn1[wo]
##
ttreat1 <- treat1
treat1[wo] <- treat2[wo]
treat2[wo] <- ttreat1[wo]
}
##
labels <- sort(unique(c(treat1, treat2)))
##
if (compmatch(labels, sep.trts)) {
if (!missing.sep.trts)
warning("Separator '", sep.trts, "' used in at least ",
"one treatment label. Try to use predefined separators: ",
"':', '-', '_', '/', '+', '.', '|', '*'.",
call. = FALSE)
##
if (!compmatch(labels, ":"))
sep.trts <- ":"
else if (!compmatch(labels, "-"))
sep.trts <- "-"
else if (!compmatch(labels, "_"))
sep.trts <- "_"
else if (!compmatch(labels, "/"))
sep.trts <- "/"
else if (!compmatch(labels, "+"))
sep.trts <- "+"
else if (!compmatch(labels, "."))
sep.trts <- "-"
else if (!compmatch(labels, "|"))
sep.trts <- "|"
else if (!compmatch(labels, "*"))
sep.trts <- "*"
else
stop("All predefined separators (':', '-', '_', '/', '+', '.', '|', '*') ",
"are used in at least one treatment label.\n ",
"Please specify a different character that should be used ",
" as separator (argument 'sep.trts').",
call. = FALSE)
}
##
if (reference.group != "")
reference.group <- setref(reference.group, labels)
##
rm(labels)
##
##
## (4) Additional checks
##
##
if (any(treat1 == treat2))
stop("Treatments must be different (arguments 'treat1' and 'treat2').",
call. = FALSE)
##
if (length(studlab) != 0)
studlab <- as.character(studlab)
else {
if (warn)
warning("No information given for argument 'studlab'. ",
"Assuming that comparisons are from independent studies.",
call. = FALSE)
studlab <- seq(along = event1)
}
##
## Check for correct number of comparisons
##
tabnarms <- table(studlab)
sel.narms <- !is.wholenumber((1 + sqrt(8 * tabnarms + 1)) / 2)
##
if (sum(sel.narms) == 1)
stop(paste0("Study '", names(tabnarms)[sel.narms],
"' has a wrong number of comparisons.",
"\n Please provide data for all treatment comparisons",
" (two-arm: 1; three-arm: 3; four-arm: 6, ...)."),
call. = FALSE)
if (sum(sel.narms) > 1)
stop(paste0("The following studies have a wrong number of comparisons: ",
paste(paste0("'", names(tabnarms)[sel.narms], "'"),
collapse = " - "),
"\n Please provide data for all treatment comparisons",
" (two-arm: 1; three-arm: 3; four-arm: 6, ...)."),
call. = FALSE)
##
## Check number of subgraphs
##
n.subnets <- netconnection(treat1, treat2, studlab)$n.subnets
##
if (n.subnets > 1)
stop(paste0("Network consists of ", n.subnets, " separate sub-networks.\n",
" Use R function 'netconnection' to identify sub-networks."),
call. = FALSE)
##
## Catch 'incr' from data:
##
if (!missing.incr)
incr <- catch("incr", mc, data, sfsp)
chknumeric(incr, min = 0)
##
if (method != "Inverse" & length(incr) > 1) {
warning("Argument 'incr' must be a single value for ",
"Mantel-Haenszel and common-effects non-central ",
"hypergeometric method. Set to zero (default).",
call. = FALSE)
incr <- 0
}
##
if (all(incr == 0) & method != "Inverse" & cc.pooled == TRUE)
cc.pooled <- FALSE
##
lengthunique <- function(x) length(unique(x))
##
##
## (5) Create analysis dataset
##
##
dat.long <- rbind(data.frame(studlab, treat = treat1, event = event1, n = n1,
.order,
stringsAsFactors = FALSE),
data.frame(studlab, treat = treat2, event = event2, n = n2,
.order,
stringsAsFactors = FALSE))
##
dat.wide <- data.frame(studlab = studlab, treat1 = treat1, treat2 = treat2,
event1 = event1, n1 = n1, event2 = event2, n2 = n2,
.order,
stringsAsFactors = FALSE)
dat.wide <- dat.wide[order(dat.wide$studlab,
dat.wide$treat1, dat.wide$treat2), ]
##
## Check for correct number of treatments
##
d.long <- unique(dat.long[, c("studlab", "treat", "event", "n")])
d.long <- d.long[order(d.long$studlab, d.long$treat), , drop = FALSE]
##
tabnarms <- table(d.long$studlab, d.long$treat)
larger.one <- function(x) any(x > 1)
sel.study <- apply(tabnarms, 1, larger.one)
##
if (sum(sel.study) == 1) {
if (details.chkdata) {
cat("Inconsistent number of events and participants:\n")
d.l <- d.long[d.long$studlab == rownames(tabnarms)[sel.study], ]
prmatrix(d.l,
quote = FALSE, right = TRUE,
rowlab = rep("", nrow(d.l)))
}
stop(paste0("Study '", rownames(tabnarms)[sel.study],
"' has inconsistent data. Please check the original data."),
call. = FALSE)
}
if (sum(sel.study) > 1) {
if (details.chkdata) {
cat("Inconsistent number of events and participants:\n")
d.l <- d.long[d.long$studlab %in% rownames(tabnarms)[sel.study], ]
prmatrix(d.l,
quote = FALSE, right = TRUE,
rowlab = rep("", nrow(d.l)))
}
##
stop(paste0("The following studies have inconsistent data: ",
paste(paste0("'", rownames(tabnarms)[sel.study], "'"),
collapse = " - "),
"\n Please check the original data."),
call. = FALSE)
}
##
get.designs <- function(x) {
net1 <-
netmeta(pairwise(studlab = x$studlab, treat = x$treat,
event = x$event, n = x$n,
sm = "RD"),
warn = FALSE)
##
if (net1$n == 2)
res <- data.frame(studlab = net1$studlab, design = net1$designs)
else
res <- nma.krahn(net1)$studies[, c("studlab", "design")]
##
res$design <- as.character(res$design)
res <- unique(res)
##
res
}
##
data$.drop <- rep(FALSE, nrow(data))
##
## Add variable 'non.event'
##
dat.long$non.event <- dat.long$n - dat.long$event
##
dat.wide$non.event1 <- dat.wide$n1 - dat.wide$event1
dat.wide$non.event2 <- dat.wide$n2 - dat.wide$event2
##
## Remove duplicated rows from dataset (due to multi-arm studies)
##
dupl <- duplicated(dat.long[, c("studlab", "treat", "event", "n")])
##
if (any(dupl))
dat.long <- dat.long[!dupl, ]
##
rm(dupl)
##
all.designs <- get.designs(dat.long)
##
## Add variable 'design' with study design
##
tdat.design <- get.designs(dat.long)
##
dat.long <- merge(dat.long, tdat.design, by = "studlab",
all.x = TRUE)
dat.wide <- merge(dat.wide, tdat.design, by = "studlab",
all.x = TRUE)
##
dat.long <- dat.long[order(dat.long$.order), ]
dat.wide <- dat.wide[order(dat.wide$.order), ]
##
names(tdat.design) <- c("studlab", ".design")
##
data <- merge(data, tdat.design,
by.x = ".studlab", by.y = "studlab",
all.x = TRUE)
data <- data[order(data$.order), ]
##
rm(tdat.design)
##
##
## (6) Stage I: setting up the data (Efthimiou et al., 2019)
##
##
## Step i. Remove all-zero or all-event studies (only MH and NCH methods)
##
if (method != "Inverse") {
events.study <- with(dat.long, tapply(event, studlab, sum))
nonevents.study <- with(dat.long, tapply(n - event, studlab, sum))
##
if (any(events.study == 0) | any(nonevents.study == 0)) {
zeroevents <- events.study == 0
allevents <- nonevents.study == 0 & events.study != 0
keep <- !(zeroevents | allevents)
##
if (warn) {
if (sum(zeroevents) == 1)
warning("Study '", names(events.study)[zeroevents],
"' without any events excluded from network meta-analysis.",
call. = FALSE)
else if (sum(zeroevents) > 1)
warning("Studies without any events excluded ",
"from network meta-analysis: ",
paste(paste0("'", names(events.study)[zeroevents], "'"),
collapse = " - "),
call. = FALSE)
##
if (sum(allevents) == 1)
warning("Study '", names(nonevents.study)[allevents],
"' with all events excluded from network meta-analysis.",
call. = FALSE)
else if (sum(allevents) > 1)
warning("Studies with all events excluded ",
"from network meta-analysis: ",
paste(paste0("'", names(nonevents.study)[allevents], "'"),
collapse = " - "),
call. = FALSE)
}
##
dat.long <- dat.long[dat.long$studlab %in% names(events.study)[keep], ,
drop = FALSE]
dat.wide <- dat.wide[dat.wide$studlab %in% names(events.study)[keep], ,
drop = FALSE]
##
data$.drop <- data$.drop | data$studlab %in% names(events.study)[!keep]
##
rm(zeroevents, allevents, keep)
}
##
rm(events.study)
}
##
## Add variable 'study' with study numbers
##
dat.long$study <- as.numeric(factor(dat.long$studlab,
levels = unique(dat.long$studlab)))
dat.wide$study <- as.numeric(factor(dat.wide$studlab,
levels = unique(dat.wide$studlab)))
##
## Sort by study and treatment
##
dat.long <- dat.long[order(dat.long$studlab, dat.long$treat), ]
dat.wide <- dat.wide[order(dat.wide$studlab,
dat.wide$treat1, dat.wide$treat2), ]
##
dat.long$incr <- 0
dat.wide$incr <- 0
data$.incr <- 0
##
## Step iii. Drop treatment arms without or all events from individual
## designs (argument 'cc.pooled' is FALSE) or add
## increment if argument 'cc.pooled' is TRUE and argument
## 'incr' is larger than zero
##
if (method != "Inverse") {
##
events.arm <- with(dat.long, tapply(event, list(design, treat), sum))
nonevents.arm <- with(dat.long, tapply(n - event, list(design, treat), sum))
##
if (any(events.arm == 0, na.rm = TRUE) |
any(nonevents.arm == 0, na.rm = TRUE)) {
##
## Identify entries without events
##
zeroevents <- events.arm == 0
zerocells <- as.data.frame(which(zeroevents, arr.ind = TRUE),
stringsAsFactors = FALSE)
##
zerocells$design <- rownames(zeroevents)[zerocells$row]
zerocells$treat <- colnames(zeroevents)[zerocells$col]
##
zero.long <- rep(0, nrow(dat.long))
zero.wide <- rep(0, nrow(dat.wide))
zero.data <- rep(0, nrow(data))
##
for (i in seq_along(zerocells$design)) {
if (!cc.pooled)
zero.long <- zero.long + (dat.long$design == zerocells$design[i] &
dat.long$treat == zerocells$treat[i])
else
zero.long <- zero.long + (dat.long$design == zerocells$design[i])
##
zero.wide <- zero.wide + (dat.wide$design == zerocells$design[i] &
(dat.wide$treat1 == zerocells$treat[i] |
dat.wide$treat2 == zerocells$treat[i]))
##
zero.data <- zero.data + (data$.design == zerocells$design[i] &
(data$.treat1 == zerocells$treat[i] |
data$.treat2 == zerocells$treat[i]))
}
##
zero.long <- zero.long > 0
zero.wide <- zero.wide > 0
zero.data <- zero.data > 0
##
## Identify entries with all events
##
allevents <- nonevents.arm == 0
allcells <- as.data.frame(which(allevents, arr.ind = TRUE),
stringsAsFactors = FALSE)
##
allcells$design <- rownames(allevents)[allcells$row]
allcells$treat <- colnames(allevents)[allcells$col]
##
all.long <- rep(0, nrow(dat.long))
all.wide <- rep(0, nrow(dat.wide))
all.data <- rep(0, nrow(data))
##
for (i in seq_along(allcells$design)) {
if (!cc.pooled)
all.long <- all.long + (dat.long$design == allcells$design[i] &
dat.long$treat == allcells$treat[i])
else
all.long <- all.long + (dat.long$design == allcells$design[i])
##
all.wide <- all.wide + (dat.wide$design == allcells$design[i] &
(dat.wide$treat1 == allcells$treat[i] |
dat.wide$treat2 == allcells$treat[i]))
##
all.data <- all.data + (data$.design == allcells$design[i] &
(data$.treat1 == allcells$treat[i] |
data$.treat2 == allcells$treat[i]))
}
##
all.long <- all.long > 0
all.wide <- all.wide > 0
all.data <- all.data > 0
##
## Identify entries with sparse binary data (i.e., with zero or
## all events)
##
sparse.long <- zero.long | all.long
sparse.wide <- zero.wide | all.wide
sparse.data <- zero.data | all.data
##
if (!cc.pooled) {
if (warn) {
if (sum(zeroevents, na.rm = TRUE) == 1)
warning("Treatment arm '", zerocells$treat,
"' without events in design '",
zerocells$design, "' excluded from network meta-analysis.",
call. = FALSE)
else if (sum(zeroevents, na.rm = TRUE) > 1)
warning("Treatment arms without events in a design excluded ",
"from network meta-analysis:\n ",
paste0("'",
paste0(paste0(zerocells$treat, " in "),
zerocells$design),
"'",
collapse = " - "),
call. = FALSE)
##
if (sum(allevents, na.rm = TRUE) == 1)
warning("Treatment arm '", allcells$treat,
"' with all events in design '",
allcells$design, "' excluded from network meta-analysis.",
call. = FALSE)
else if (sum(allevents, na.rm = TRUE) > 1)
warning("Treatment arms with all events in a design excluded ",
"from network meta-analysis:\n ",
paste0("'",
paste0(paste0(allcells$treat, " in "),
allcells$design),
"'",
collapse = " - "),
call. = FALSE)
}
##
dat.long <- dat.long[!sparse.long, , drop = FALSE]
dat.wide <- dat.wide[!sparse.wide, , drop = FALSE]
data$.drop <- data$.drop | sparse.data
}
else {
dat.long$incr[sparse.long] <- incr
##
dat.long$event[sparse.long] <- dat.long$event[sparse.long] + incr
dat.long$non.event[sparse.long] <- dat.long$non.event[sparse.long] + incr
dat.long$n[sparse.long] <- dat.long$n[sparse.long] + 2 * incr
##
dat.wide$incr[sparse.wide] <- incr
##
data$.incr[sparse.data] <- incr
}
##
rm(zeroevents, zerocells, zero.long, zero.wide, zero.data,
allevents, allcells, all.long, all.wide, all.data,
sparse.long, sparse.wide, sparse.data)
}
##
rm(events.arm, nonevents.arm)
}
##
## Step iv. Remove designs with single treatment arm from dataset
##
if (method != "Inverse") {
d.single <- with(dat.long, tapply(treat, design, lengthunique))
##
if (any(d.single == 1, na.rm = TRUE)) {
single <- !is.na(d.single) & d.single == 1
design.single <- names(d.single)[single]
##
if (warn)
if (sum(single) == 1)
warning("Design '", design.single,
"' with single treatment arm excluded ",
"from network meta-analysis.",
call. = FALSE)
else
warning("Designs with single treatment arm excluded ",
"from network meta-analysis: ",
paste(paste0("'", design.single, "'"),
collapse = " - "),
call. = FALSE)
##
dat.long <- dat.long[!(dat.long$design %in% design.single), , drop = FALSE]
dat.wide <- dat.wide[!(dat.wide$design %in% design.single), , drop = FALSE]
##
data$.drop <- data$.drop | data$.design %in% design.single
##
rm(single, design.single)
}
##
rm(d.single)
}
##
dat.long <- dat.long[, c("studlab", "treat",
"event", "non.event", "n", "incr",
"design", "study", ".order")]
dat.wide <- dat.wide[, c("studlab", "treat1", "treat2",
"event1", "event2", "non.event1", "non.event2",
"n1", "n2", "incr",
"design", "study", ".order")]
##
dat.long$studlab <- as.character(dat.long$studlab)
dat.long$design <- as.character(dat.long$design)
dat.long$treat <- as.character(dat.long$treat)
##
dat.wide$studlab <- as.character(dat.wide$studlab)
dat.wide$design <- as.character(dat.wide$design)
dat.wide$treat1 <- as.character(dat.wide$treat1)
dat.wide$treat2 <- as.character(dat.wide$treat2)
##
o <- order(dat.wide$.order)
studlab <- dat.wide$studlab[o]
treat1 <- dat.wide$treat1[o]
treat2 <- dat.wide$treat2[o]
##
event1 <- dat.wide$event1[o]
event2 <- dat.wide$event2[o]
n1 <- dat.wide$n1[o]
n2 <- dat.wide$n2[o]
##
trts <- sort(unique(c(treat1, treat2)))
n.treat <- length(trts)
n.studies <- length(unique(studlab))
m <- length(studlab)
##
treat1.pos <- match(treat1, trts)
treat2.pos <- match(treat2, trts)
##
## Calculate adjacency matrix
##
B <- createB(treat1.pos, treat2.pos, ncol = n.treat)
##
M <- t(B) %*% B # unweighted Laplacian matrix
D <- diag(diag(M)) # diagonal matrix
A <- D - M # adjacency matrix (n x n)
##
rownames(A) <- colnames(A) <- trts
##
rm(B, M, D)
##
## Empty matrices for results
##
NAmatrix <- matrix(NA, nrow = n.treat, ncol = n.treat)
rownames(NAmatrix) <- colnames(NAmatrix) <- trts
##
TE.common <- seTE.common <- NAmatrix
TE.direct.common <- seTE.direct.common <- NAmatrix
Q.direct <- tau2.direct <- I2.direct <- NAmatrix
##
##
## (7) Conduct classic network meta-analysis using inverse variance
## method
##
##
dat.iv <- dat.long[order(dat.long$.order), ]
##
if (method == "Inverse") {
if (missing(warn))
warn.iv <- gs("warn")
else
warn.iv <- warn
incr.iv <- incr
allstudies.iv <- allstudies
}
else {
warn.iv <- FALSE
incr.iv <- incr * cc.pooled
allstudies.iv <- cc.pooled
}
##
p.iv <- pairwise(studlab = dat.iv$studlab,
treat = dat.iv$treat,
event = dat.iv$event,
n = dat.iv$n,
data = dat.iv,
sm = sm,
incr = incr.iv,
allincr = allincr, addincr = addincr,
allstudies = allstudies.iv)
##
net.iv <- netmeta(p.iv,
level = level, level.ma = level.ma,
common = common, random = random,
prediction = prediction, level.predict = level.predict,
reference.group = reference.group,
baseline.reference = baseline.reference,
all.treatments = all.treatments,
seq = seq,
tau.preset = tau.preset,
tol.multiarm = tol.multiarm,
tol.multiarm.se = tol.multiarm.se,
details.chkmultiarm = details.chkmultiarm,
sep.trts = sep.trts,
nchar.trts = nchar.trts,
backtransf = backtransf,
title = title,
keepdata = keepdata,
warn = warn.iv)
##
if (method == "Inverse")
return(net.iv)
else {
net.iv$Cov.common[!is.na(net.iv$Cov.common)] <- NA
net.iv$Cov.random[!is.na(net.iv$Cov.random)] <- NA
}
##
##
## (8) Stage 2: Direct meta-analyses per design (MH and NCH methods)
##
##
n.d <- tapply(dat.long$treat, dat.long$design, lengthunique)
k.d <- tapply(dat.long$studlab, dat.long$design, lengthunique)
##
designs <- names(k.d)
d <- length(designs)
seq.d <- seq_len(d)
##
dat.design <- vector("list", d)
names(dat.design) <- designs
##
for (i in seq.d)
dat.design[[i]] <- dat.long[dat.long$design == designs[i], , drop = FALSE]
##
if (method == "MH") {
##
## MH method
##
treat.per.design <- vector("list", d)
studies.in.design <- vector("list", d)
##
c.xy <- vector("list", d)
d.xy <- vector("list", d)
C.xy <- vector("list", d)
L.xy <- vector("list", d)
##
U.xyy <- vector("list", d)
U.xyz <- vector("list", d)
##
t.pl <- vector("list", d)
##
ps1 <- ps2 <- ps3 <- ps4 <- vector("list", d)
##
L.bar.xy <- vector("list", d)
##
U.plus.xx <- vector("list", d)
##
U.new <- vector("list", d)
##
U.plus.xy <- vector("list", d)
##
Var.Lbar <- vector("list", d)
##
CoVar.Lbar <- vector("list", d)
##
length.y <- sum(n.d - 1)
##
y <- c(rep(0, length.y))
##
V1 <- matrix(rep(0, length.y * length.y), nrow = length.y)
V2 <- matrix(rep(0, length.y * length.y), nrow = length.y)
##
X <- matrix(0, nrow = length.y, ncol = n.treat - 1)
##
counter1 <- counter2 <- counter3 <- 0
##
list1 <- matrix(0, nrow = length.y, ncol = 2)
##
N.j <- rep(0, d)
##
if (d > 1)
for (i in 2:d)
N.j[i] <- N.j[i - 1] + n.d[i - 1] - 1
##
## Loop for designs
##
for (i in seq.d) {
treat.per.design[[i]] <- unique(dat.design[[i]]$treat)
studies.in.design[[i]] <- unique(dat.design[[i]]$study)
##
## List of studies in each design
##
## Recode the studies in each design
##
for (j in seq_along(dat.design[[i]]$study))
for (k in seq_len(k.d[i]))
if (dat.design[[i]]$study[j] == studies.in.design[[i]][k])
dat.design[[i]]$id.s[j] <- k
##
## Recode the treatments in each design
##
for (j in seq_along(dat.design[[i]]$study))
for (k in seq_len(n.d[i]))
if (dat.design[[i]]$treat[j] == treat.per.design[[i]][k])
dat.design[[i]]$id.t[j] <- k
##
## Calculate total number of patients per studies
##
for (j in seq_along(dat.design[[i]]$studlab))
dat.design[[i]]$n.study[j] <-
with(dat.design[[i]], sum(n[which(study == study[j])]))
##
## Define c.xy and d.xy
##
c.xy[[i]] <- array(rep(0, k.d[i] * n.d[i] * n.d[i]),
dim = c(n.d[i], n.d[i], k.d[i]))
##
d.xy[[i]] <- array(rep(0, k.d[i] * n.d[i] * n.d[i]),
dim = c(n.d[i], n.d[i], k.d[i]))
##
for (st in seq_len(k.d[i]))
for (t1 in seq_len(n.d[i]))
for (t2 in seq_len(n.d[i])) {
c.xy[[i]][t1, t2, st] <-
with(dat.design[[i]],
sum( event[which(id.s == st & id.t == t1)]) *
sum(non.event[which(id.s == st & id.t == t2)]) /
n.study[id.s == st][1])
##
d.xy[[i]][t1, t2, st] <-
with(dat.design[[i]],
(sum( event[which(id.s == st & id.t == t1)]) +
sum(non.event[which(id.s == st & id.t == t2)])) /
n.study[id.s == st][1])
}
##
## Define C.xy
##
C.xy[[i]] <- matrix(rep(0, n.d[i] * n.d[i]), nrow = n.d[i])
##
for (j in seq_len(n.d[i]))
for (k in seq_len(n.d[i]))
C.xy[[i]][j, k] <- sum(c.xy[[i]][j, k, ])
##
## Define L.xy
##
L.xy[[i]] <- matrix(rep(0, n.d[i] * n.d[i]), nrow = n.d[i])
for (j in seq_len(n.d[i]))
for (k in seq_len(n.d[i]))
L.xy[[i]][j, k] <- log(C.xy[[i]][j, k] / C.xy[[i]][k, j])
##
## Calculate the variance of L.xy (dimension n.d[i] x n.d[i])
##
U.xyy[[i]] <- matrix(rep(0, n.d[i] * n.d[i]), nrow = n.d[i])
for (j in seq_len(n.d[i]))
for (k in seq_len(n.d[i]))
U.xyy[[i]][j, k] <-
sum(c.xy[[i]][j, k, ] * d.xy[[i]][j, k, ]) /
(2 * C.xy[[i]][j, k]^2) +
sum(c.xy[[i]][j, k, ] * d.xy[[i]][k, j, ] + c.xy[[i]][k, j, ] *
d.xy[[i]][j, k, ]) / (2 * C.xy[[i]][j, k] * C.xy[[i]][k, j]) +
sum(c.xy[[i]][k, j, ] * d.xy[[i]][k, j, ]) / (2 * C.xy[[i]][k, j]^2)
##
## Calculate the covariance matrix U.xyz
##
t.pl[[i]] = array(rep(0, k.d[i] * n.d[i] * n.d[i]),
dim = c(n.d[i], n.d[i], k.d[i]))
##
for (j in seq_len(k.d[i]))
t.pl[[i]][ , , j] <- with(dat.design[[i]], n.study[id.s == j][1])
##
U.xyz[[i]] <- array(rep(0, n.d[i] * n.d[i] * n.d[i]),
dim = c(n.d[i], n.d[i], n.d[i]))
##
## Per study ...
##
for (t1 in seq_len(n.d[i])) {
for (t2 in seq_len(n.d[i])) {
for (t3 in seq_len(n.d[i])) {
for (st in seq_len(k.d[i])) {
sel1 <- with(dat.design[[i]], which(id.s == st & id.t == t1))
sel2 <- with(dat.design[[i]], which(id.s == st & id.t == t2))
sel3 <- with(dat.design[[i]], which(id.s == st & id.t == t3))
##
ps1[[i]][st] <-
with(dat.design[[i]],
event[sel1] /
(t.pl[[i]][1, 1, st])^2 *
non.event[sel2] * non.event[sel3] *
(t1 != t2) * (t1 != t3) * (t2 != t3))
##
ps2[[i]][st] <-
with(dat.design[[i]],
n[sel1] / (t.pl[[i]][1, 1, st])^2 *
non.event[sel2] * event[sel3] *
(t1 != t2) * (t1 != t3) * (t2 != t3))
##
ps3[[i]][st] <-
with(dat.design[[i]],
n[sel1] / (t.pl[[i]][1, 1, st])^2 *
event[sel2] * non.event[sel3] *
(t1 != t2) * (t1 != t3) * (t2 != t3))
##
ps4[[i]][st] <-
with(dat.design[[i]],
non.event[sel1] / (t.pl[[i]][1, 1, st])^2 *
event[sel2] * event[sel3] *
(t1 != t2) * (t1 != t3) * (t2 != t3))
}
##
U.xyz[[i]][t1, t2, t3] <-
sum(ps1[[i]][]) / (3 * C.xy[[i]][t1, t2] * C.xy[[i]][t1, t3]) +
sum(ps2[[i]][]) / (3 * C.xy[[i]][t1, t2] * C.xy[[i]][t3, t1]) +
sum(ps3[[i]][]) / (3 * C.xy[[i]][t2, t1] * C.xy[[i]][t1, t3]) +
sum(ps4[[i]][]) / (3 * C.xy[[i]][t2, t1] * C.xy[[i]][t3, t1])
}
}
}
##
## Calculate L.bar.xy
##
L.bar.xy[[i]] <- matrix(rep(0, n.d[i] * n.d[i]), nrow = n.d[i])
for (t1 in seq_len(n.d[i]))
for (t2 in seq_len(n.d[i]))
L.bar.xy[[i]][t1, t2] <-
(sum(L.xy[[i]][t1, ]) - sum(L.xy[[i]][t2, ])) / n.d[i]
##
## Calculate U.plus.xx
##
for (t1 in seq_len(n.d[i]))
U.xyy[[i]][t1, t1] <- 0
##
U.plus.xx[[i]] <- rep(0, n.d[i])
for (t1 in seq_len(n.d[i]))
U.plus.xx[[i]][t1] <-
sum(U.xyy[[i]][t1, seq_len(n.d[i])]) + sum(U.xyz[[i]][t1, , ])
##
## Calculate U.plus.xy
##
U.new[[i]] <- array(rep(0, n.d[i] * n.d[i] * n.d[i]),
dim = c(n.d[i], n.d[i], n.d[i]))
##
for (t1 in seq_len(n.d[i]))
for (t2 in seq_len(n.d[i]))
for (t3 in seq_len(n.d[i]))
U.new[[i]][t1, t2, t3] <-
(t1 != t2) * (t1 != t3) * (t2 != t3) *
U.xyz[[i]][t1, t2, t3] +
(t1 != t2) * (t2 == t3) * U.xyy[[i]][t1, t2]
##
U.plus.xy[[i]] = matrix(rep(0, n.d[i] * n.d[i]), nrow = n.d[i])
##
for (t1 in seq_len(n.d[i]))
for (t2 in seq_len(n.d[i]))
U.plus.xy[[i]][t1, t2] <-
sum(U.new[[i]][seq_len(n.d[i]), t1, t2]) -
sum(U.new[[i]][t1, t2, seq_len(n.d[i])]) -
sum(U.new[[i]][t2, t1, seq_len(n.d[i])]) +
U.new[[i]][t1, t2, t2]
##
## Variance of L.bar.xy
##
Var.Lbar[[i]] <- matrix(rep(0, n.d[i] * n.d[i]), nrow = n.d[i])
for (t1 in seq_len(n.d[i]))
for (t2 in seq_len(n.d[i]))
Var.Lbar[[i]][t1, t2] <-
(U.plus.xx[[i]][t1] - 2 * U.plus.xy[[i]][t1, t2] +
U.plus.xx[[i]][t2]) / n.d[i]^2
##
## Covariance of L.bar.xy. Only a subset of covariances are
## calculate here, i.e. cov(L.bar_(1, t1), L.bar_(1, t2))
##
CoVar.Lbar[[i]] <- matrix(rep(0, n.d[i]^2), nrow = n.d[i])
for (t1 in seq_len(n.d[i]))
for (t2 in seq_len(n.d[i]))
CoVar.Lbar[[i]][t1, t2] <-
(U.plus.xx[[i]][1] - U.plus.xy[[i]][1, t2] -
U.plus.xy[[i]][t1, 1] +
U.plus.xy[[i]][t1, t2]) / n.d[i]^2
##
## Define matrix X
##
for (j in seq_along(dat.design[[i]]$studlab))
for (k in seq_along(trts))
if (dat.design[[i]]$treat[j] == trts[k])
dat.design[[i]]$id.t2[j] <- k
##
##
## Create y, the vector of treatment effects from each study. Only
## effects vs the first treatment are needed. y is coded as OR
## 1vsX
##
for (j in seq_len(n.d[i] - 1))
y[j + counter1] <- L.bar.xy[[i]][1, j + 1]
##
counter1 <- counter1 + n.d[i] - 1
##
## Create V, the matrix of covariances of treatment effects from
## each study. Only covariances of effects vs the first treatment
## are needed.
##
for (j in seq_len(n.d[i] - 1))
for (k in seq_len(n.d[i] - 1))
V1[j + counter2, k + counter2] <- (k == j) * Var.Lbar[[i]][1, j + 1]
##
counter2 <- counter2 + n.d[i] - 1
##
for (j in 2:(n.d[i]))
for (k in 2:(n.d[i]))
V2[j + counter3 - 1, k + counter3 - 1] <-
(k != j) * CoVar.Lbar[[i]][j, k]
##
counter3 <- counter3 + n.d[i] - 1
##
for (j in seq_len(n.d[i] - 1)) {
list1[N.j[i] + j, 1] <- dat.design[[i]]$id.t2[[1]]
list1[N.j[i] + j, 2] <- dat.design[[i]]$id.t2[[j + 1]]
}
##
## Drop unnecessary variables
##
dat.design[[i]]$id.s <- NULL
dat.design[[i]]$id.t <- NULL
dat.design[[i]]$id.t2 <- NULL
dat.design[[i]]$n.study <- NULL
}
##
V <- V1 + V2
##
basic.contrasts <- 2:n.treat
##
for (i in 1:length.y)
for (k in 1:(n.treat - 1)) {
if (list1[i, 1] == basic.contrasts[k])
X[i, k] = -1
if (list1[i, 2] == basic.contrasts[k])
X[i, k] = 1
}
##
W <- solve(V)
##
TE.basic <- solve(t(X) %*% W %*% X) %*% t(X) %*% W %*% y
}
else if (method == "NCH") {
##
## NCH method
##
dat.long$ttt <- 0
##
for (k in 1:n.treat)
for (i in seq_along(dat.long$studlab))
if (dat.long$treat[i] == trts[k])
dat.long$ttt[i] <- k
##
dat.long$treat <- as.numeric(dat.long$ttt)
dat.long$ttt <- NULL
##
dat.long$treat <- as.numeric(dat.long$treat)
##
dat.long <- dat.long[order(dat.long$studlab, dat.long$treat), ] # necessary ???
##
for (i in unique(dat.long$studlab)) {
counter <- 1
for (j in seq_along(dat.long$studlab))
if (dat.long$studlab[j] == i) {
dat.long$count[j] <- counter
counter <- counter + 1
}
}
##
max.arms <- max(dat.long$count)
##
d1 <- reshape(dat.long, idvar = "studlab",
timevar = "count", direction = "wide")
##
d1 <- d1[order(d1$studlab), ]
##
d1$N1 <- 0 # d1$n.all = 0
d1$narms <- 0
##
for (i in seq_len(max.arms)) {
ev <- paste0("event.", i)
tot <- paste0("n.", i)
d1$N1 <- rowSums(cbind(d1$N1, d1[, colnames(d1) == ev]),
na.rm = TRUE)
## d1$n.all <- rowSums(cbind(d1$n.all, d1[, colnames(d1) == tot]), na.rm = TRUE)
}
##
for (i in seq_along(d1$studlab))
for (k in 1:max.arms) {
ev <- paste0("event.", k)
if (!is.na(d1[, colnames(d1) == ev][i]))
d1$narms[i] <- k
}
##
for (i in seq_along(colnames(d1)))
for (k in seq_along(colnames(d1))) {
if (colnames(d1)[k] == paste0("treat.", i))
colnames(d1)[k] = paste0("t", i)
##
if (colnames(d1)[k] == paste0("event.", i))
colnames(d1)[k] = paste0("r", i)
##
if (colnames(d1)[k] == paste0("n.", i))
colnames(d1)[k] = paste0("n", i)
}
##
## Likelihood function
##
myLik1 <- function(mypar) {
x <- mypar
##
myLogLik1 <- myLogLik2 <- myLogLik3 <- rep(0, length(d1$studlab))
##
for (i in seq_along(d1$studlab)) {
for (k in 2:d1$narms[i]) {
myLogLik1[i] <-
myLogLik1[i] +
d1[, colnames(d1) == paste0("r", k)][i] *
(x[d1[, colnames(d1) == paste0("t", k)][i]] -
x[d1$t1[i]] * (d1$t1[i] != 1))
##
myLogLik2[i] <-
myLogLik2[i] +
d1[, colnames(d1) == paste0("n", k)][i] *
exp(x[d1[, colnames(d1) == paste0("t", k)][i]] -
x[d1$t1[i]] * (d1$t1[i] != 1))
##
myLogLik3[i] <- -d1$N1[i] * log(d1$n1[i] + myLogLik2[i])
}
}
##
myLogLik <- sum(myLogLik1 + myLogLik3)
##
myLogLik
}
##
opt <- optim(rep(0, n.treat), myLik1, method = "L-BFGS-B",
lower = -Inf, upper = Inf,
control = list(fnscale = -1, maxit = 10000),
hessian = TRUE)
##
W <- solve(-opt$hessian[2:n.treat, 2:n.treat])
##
TE.basic <- -(opt$par)[2:n.treat]
}
##
## Define H matrix
##
H <- matrix(0,
nrow = n.treat * ((n.treat - 1) / 2),
ncol = n.treat - 1)
##
diag(H) <- 1
##
if (n.treat > 2) {
t1 <- c()
t2 <- c()
for (i in 2:(n.treat - 1))
for (j in (i + 1):(n.treat)) {
t1 <- rbind(t1, i)
t2 <- rbind(t2, j)
}
##
h1 <- matrix(c(t1, t2), nrow = nrow(t1))
##
for (i in 1:((n.treat - 1) * (n.treat - 2) / 2))
for (j in 1:(n.treat - 1))
H[i + n.treat - 1, j] <- -(h1[i, 1] == j + 1) + (h1[i, 2] == j + 1)
}
##
## Common effects matrix
##
d.hat <- H %*% TE.basic
##
TE.common[lower.tri(TE.common, diag = FALSE)] <- d.hat
TE.common <- t(TE.common)
TE.common[lower.tri(TE.common, diag = FALSE)] <- -d.hat
diag(TE.common) <- 0
##
## Matrix with standard errors
##
if (method == "MH")
cov.d.hat <- H %*% solve(t(X) %*% W %*% X) %*% t(H)
else
cov.d.hat <- H %*% W %*% t(H)
##
seTE.common[lower.tri(seTE.common, diag = FALSE)] <- sqrt(diag(cov.d.hat))
seTE.common <- t(seTE.common)
seTE.common[lower.tri(seTE.common, diag = FALSE)] <- sqrt(diag(cov.d.hat))
diag(seTE.common) <- 0
##
## Confidence intervals
##
ci.f <- ci(TE.common, seTE.common, level = level.ma)
##
## Inconsistency global
##
if (method == "MH") {
Q <- as.vector(t(y - X %*% TE.basic) %*% solve(V) %*%
(y - X %*% TE.basic))
df.Q <- sum(n.d - 1) - (n.treat - 1)
pval.Q <- pvalQ(Q, df.Q)
}
else {
Q <- NA
df.Q <- NA
pval.Q <- NA
}
##
##
## (9) Inconsistency evaluation: direct MH estimates
##
##
B.matrix <- createB(treat1.pos, treat2.pos)
B.matrix <- unique(B.matrix)
colnames(B.matrix) <- trts
##
for (i in seq_len(nrow(B.matrix))) {
sel.treat1 <- colnames(B.matrix)[B.matrix[i, ] == 1]
sel.treat2 <- colnames(B.matrix)[B.matrix[i, ] == -1]
selstud <- treat1 == sel.treat1 & treat2 == sel.treat2
##
m.i <- metabin(event1, n1, event2, n2, subset = selstud,
method = "MH", sm = "OR",
incr = incr, allincr = allincr, addincr = addincr,
allstudies = allstudies, MH.exact = !cc.pooled,
method.tau = "DL", method.tau.ci = "",
Q.Cochrane = FALSE,
warn.deprecated = FALSE)
##
TE.i <- m.i$TE.common
seTE.i <- m.i$seTE.common
Q.i <- m.i$Q
tau2.i <- m.i$tau2
I2.i <- m.i$I2
##
TE.direct.common[sel.treat1, sel.treat2] <- TE.i
seTE.direct.common[sel.treat1, sel.treat2] <- seTE.i
Q.direct[sel.treat1, sel.treat2] <- Q.i
tau2.direct[sel.treat1, sel.treat2] <- tau2.i
I2.direct[sel.treat1, sel.treat2] <- I2.i
##
TE.direct.common[sel.treat2, sel.treat1] <- -TE.i
seTE.direct.common[sel.treat2, sel.treat1] <- seTE.i
Q.direct[sel.treat2, sel.treat1] <- Q.i
tau2.direct[sel.treat2, sel.treat1] <- tau2.i
I2.direct[sel.treat2, sel.treat1] <- I2.i
}
##
rm(sel.treat1, sel.treat2, selstud, m.i, TE.i, seTE.i)
##
ci.d <- ci(TE.direct.common, seTE.direct.common, level = level.ma)
labels <- sort(unique(c(treat1, treat2)))
##
if (!is.null(seq))
seq <- setseq(seq, labels)
else {
seq <- labels
if (is.numeric(seq))
seq <- as.character(seq)
}
res <- list(studlab = studlab,
treat1 = treat1,
treat2 = treat2,
##
TE = data$.TE[!data$.drop],
seTE = data$.seTE[!data$.drop],
seTE.adj = rep(NA, sum(!data$.drop)),
seTE.adj.common = rep(NA, sum(!data$.drop)),
seTE.adj.random = rep(NA, sum(!data$.drop)),
##
design = designs(treat1, treat2, studlab)$design,
##
event1 = event1,
event2 = event2,
n1 = n1,
n2 = n2,
##
k = n.studies,
m = m,
n = length(trts),
d = d,
##
trts = trts,
k.trts = rowSums(A),
n.trts = NA,
events.trts = NA,
##
studies = NA,
narms = NA,
##
designs = designs,
##
TE.common = TE.common,
seTE.common = seTE.common,
lower.common = ci.f$lower,
upper.common = ci.f$upper,
statistic.common = ci.f$statistic,
pval.common = ci.f$p,
##
TE.random = NAmatrix,
seTE.random = NAmatrix,
lower.random = NAmatrix,
upper.random = NAmatrix,
statistic.random = NAmatrix,
pval.random = NAmatrix,
##
seTE.predict = NAmatrix,
lower.predict = NAmatrix,
upper.predict = NAmatrix,
##
prop.direct.common = NA,
prop.direct.random = NA,
##
TE.direct.common = TE.direct.common,
seTE.direct.common = seTE.direct.common,
lower.direct.common = ci.d$lower,
upper.direct.common = ci.d$upper,
statistic.direct.common = ci.d$statistic,
pval.direct.common = ci.d$p,
##
TE.direct.random = NAmatrix,
seTE.direct.random = NAmatrix,
lower.direct.random = NAmatrix,
upper.direct.random = NAmatrix,
statistic.direct.random = NAmatrix,
pval.direct.random = NAmatrix,
##
Q.direct = Q.direct,
tau.direct = sqrt(tau2.direct),
tau2.direct = tau2.direct,
I2.direct = I2.direct,
##
TE.indirect.common = NA,
seTE.indirect.common = NA,
lower.indirect.common = NA,
upper.indirect.common = NA,
statistic.indirect.common = NA,
pval.indirect.common = NA,
##
TE.indirect.random = NA,
seTE.indirect.random = NA,
lower.indirect.random = NA,
upper.indirect.random = NA,
statistic.indirect.random = NA,
pval.indirect.random = NA,
##
Q = NA,
df.Q = NA,
pval.Q = NA,
I2 = NA, lower.I2 = NA, upper.I2 = NA,
tau = NA,
##
Q.heterogeneity = NA,
df.Q.heterogeneity = NA,
pval.Q.heterogeneity = NA,
Q.inconsistency = Q,
df.Q.inconsistency = df.Q,
pval.Q.inconsistency = pval.Q,
##
Q.decomp = NA,
##
A.matrix = A,
H.matrix = H,
##
n.matrix = NA,
events.matrix = NA,
##
P.common = NA,
P.random = NA,
##
Cov.common = net.iv$Cov.common,
Cov.random = net.iv$Cov.random,
##
sm = sm,
method = method,
##
incr = incr,
allincr = allincr,
addincr = addincr,
allstudies = allstudies,
cc.pooled = cc.pooled,
##
level = level,
level.ma = level.ma,
common = common,
random = random,
##
prediction = prediction,
level.predict = level.predict,
##
reference.group = reference.group,
baseline.reference = baseline.reference,
all.treatments = all.treatments,
seq = seq,
##
tau.preset = tau.preset,
##
tol.multiarm = tol.multiarm,
tol.multiarm.se = tol.multiarm.se,
details.chkmultiarm = details.chkmultiarm,
details.chkdata = details.chkdata,
##
sep.trts = sep.trts,
nchar.trts = nchar.trts,
##
func.inverse = deparse(substitute(func.inverse)),
##
backtransf = backtransf,
##
title = title,
##
data = if (keepdata) data else NULL,
data.design = dat.design,
##
warn = warn,
call = match.call(),
version = packageDescription("netmeta")$Version
)
##
class(res) <- c("netmetabin", "netmeta")
##
## Add results for indirect treatment estimates
##
n <- res$n
##
res$prop.direct.common <-
netmeasures(res, random = FALSE, warn = warn)$proportion
if (is.logical(res$prop.direct.common))
res$prop.direct.common <- as.numeric(res$prop.direct.common)
##
P.common <- P.random <- matrix(NA, n, n)
colnames(P.common) <- rownames(P.common) <-
colnames(P.random) <- rownames(P.random) <- trts
##
if (n == 2) {
##
## For two treatments only direct evidence is available
##
res$prop.direct.common <- 1
names(res$prop.direct.common) <- paste(labels, collapse = sep.trts)
##
sel <- row(P.common) != col(P.common)
P.common[sel] <- 1
}
else {
k <- 0
for (i in 1:(n - 1)) {
for (j in (i + 1):n) {
k <- k + 1
P.common[i, j] <- P.common[j, i] <- res$prop.direct.common[k]
}
}
}
##
## Set direct evidence estimates to 0 if only indirect evidence is available
## (otherwise indirect estimates would be NA as direct estimates are NA)
##
TE.direct.common <- res$TE.direct.common
##
TE.direct.common[abs(P.common) < .Machine$double.eps^0.5] <- 0
##
## Indirect estimate is NA if only direct evidence is available
##
res$P.common <- P.common
##
P.common[abs(P.common - 1) < .Machine$double.eps^0.5] <- NA
P.common[P.common > 1] <- NA
##
## Common effects model
##
ci.if <- ci((res$TE.common - P.common * TE.direct.common) / (1 - P.common),
sqrt(res$seTE.common^2 / (1 - P.common)),
level = level)
##
res$TE.indirect.common <- ci.if$TE
res$seTE.indirect.common <- ci.if$seTE
##
res$lower.indirect.common <- ci.if$lower
res$upper.indirect.common <- ci.if$upper
##
res$statistic.indirect.common <- ci.if$statistic
res$pval.indirect.common <- ci.if$p
##
## No results for random effects model
##
res$prop.direct.random <- res$prop.direct.common
res$prop.direct.random[!is.na(res$prop.direct.random)] <- NA
res$P.random <- P.random
##
res$TE.indirect.random <- res$seTE.indirect.random <-
res$lower.indirect.random <- res$upper.indirect.random <-
res$statistic.indirect.random <- res$pval.indirect.random <-
NAmatrix
##
## Study overview
##
p0 <- prepare(rep(1, nrow(dat.wide)),
rep(1, nrow(dat.wide)),
dat.wide$treat1,
dat.wide$treat2,
dat.wide$studlab,
func.inverse = func.inverse)
##
tdata <- data.frame(studies = p0$studlab, narms = p0$narms,
stringsAsFactors = FALSE)
##
tdata <- tdata[!duplicated(tdata[, c("studies", "narms")]), , drop = FALSE]
res$studies <- tdata$studies
res$narms <- tdata$narms
##
if (all(suppressWarnings(!is.na(as.numeric(res$studies))))) {
o <- order(as.numeric(res$studies))
res$studies <- res$studies[o]
res$narms <- res$narms[o]
}
##
res$data <- merge(res$data,
data.frame(.studlab = res$studies,
.narms = res$narms),
by = ".studlab", all.x = TRUE)
res$data <- res$data[order(res$data$.order), ]
res$data$.order <- NULL
rownames(res$data) <- seq_len(nrow(res$data))
res$n.matrix <- netmatrix(res, n1 + n2, func = "sum")
##
dat.n <- data.frame(studlab = c(studlab, studlab),
treat = c(treat1, treat2),
n = c(n1, n2))
dat.n <- dat.n[!duplicated(dat.n[, c("studlab", "treat")]), ]
dat.n <- by(dat.n$n, dat.n$treat, sum, na.rm = TRUE)
res$n.trts <- as.vector(dat.n[trts])
names(res$n.trts) <- trts
##
res$events.matrix <- netmatrix(res, event1 + event2, func = "sum")
##
dat.e <- data.frame(studlab = c(studlab, studlab),
treat = c(treat1, treat2),
n = c(event1, event2))
dat.e <- dat.e[!duplicated(dat.e[, c("studlab", "treat")]), ]
dat.e <- by(dat.e$n, dat.e$treat, sum, na.rm = TRUE)
res$events.trts <- as.vector(dat.e[trts])
names(res$events.trts) <- trts
##
## Backward compatibility
##
res$fixed <- res$common
res$comb.fixed <- res$common
res$comb.random <- res$random
##
res$seTE.adj.fixed <- res$seTE.adj.common
##
res$TE.fixed <- res$TE.common
res$seTE.fixed <- res$seTE.common
res$lower.fixed <- res$lower.common
res$upper.fixed <- res$upper.common
res$statistic.fixed <- res$statistic.common
res$pval.fixed <- res$pval.common
##
res$prop.direct.fixed <- res$prop.direct.common
##
res$TE.direct.fixed <- res$TE.direct.common
res$seTE.direct.fixed <- res$seTE.direct.common
res$lower.direct.fixed <- res$lower.direct.common
res$upper.direct.fixed <- res$upper.direct.common
res$statistic.direct.fixed <- res$statistic.direct.common
res$pval.direct.fixed <- res$pval.direct.common
##
res$TE.indirect.fixed <- res$TE.indirect.common
res$seTE.indirect.fixed <- res$seTE.indirect.common
res$lower.indirect.fixed <- res$lower.indirect.common
res$upper.indirect.fixed <- res$upper.indirect.common
res$statistic.indirect.fixed <- res$statistic.indirect.common
res$pval.indirect.fixed <- res$pval.indirect.common
##
res$P.fixed <- res$P.common
res$Cov.fixed <- res$Cov.common
res
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.