Nothing
#' Linear hypotheses for natural effect models
#'
#' @description \code{neLht} allows to calculate linear combinations of natural effect model parameter estimates.\cr \code{neEffdecomp} automatically extracts relevant causal parameter estimates from a natural effect model.
#' @param model a fitted natural effect model object.
#' @param xRef a vector including reference levels for the exposure, \emph{x*} and \emph{x}, at which natural effect components need to be evaluated (see details).
#' @param covLev a vector including covariate levels at which natural effect components need to be evaluated (see details).
#' @param ... additional arguments (passed to \code{\link[multcomp]{glht}}).
#' @return An object of class \code{c("neLht", "glht")} (see \code{\link[multcomp]{glht}}).
#' If the bootstrap is used for obtaining standard errors when fitting the \code{\link{neModel}} object, the returned object additionally inherits from class \code{"neLhtBoot"}.
#' \code{neEffdecomp} returns an object that additionally inherits from class \code{"neEffdecomp"}.
#'
#' See \code{\link{neLht-methods}} for methods for \code{neLht} objects (and \code{\link[=coef.glht]{glht-methods}} for additional methods for \code{glht} objects).
#' @details \code{neLht} is a wrapper of \code{\link[multcomp]{glht}} and offers the same functionality (see `Details' section of \code{\link[multcomp]{glht}} for details on argument specification).
#' It returns objects that inherit from the class \code{"neLht"} in order to make output of their corresponding methods (see \code{\link{neLht-methods}}) more compatible for natural effect models
#' containing bootstrap variance-covariance matrices and standard errors.
#'
#' \code{neEffdecomp} is a convenience function that automatically extracts causal parameter estimates from a natural effect model
#' and derives natural effect components.
#' That is, natural direct, natural indirect and total causal effect estimates are returned if no exposure-mediator interaction is modelled (i.e. two-way decomposition).
#' If mediated interaction is allowed for in the natural effect model, there are two ways of decomposing the total effect into (natural) direct and indirect effects components:
#' either as the sum of the pure direct and the total indirect effect or as the sum of the pure indirect and the total direct effect (i.e. three-way decomposition).
#' In total, five causal effect estimates are returned in this case.
#'
#' For continuous exposures, default exposure levels at which natural effect components are evaluated are \emph{x*} = 0 and \emph{x} = 1.
#' For multicategorical exposures, default levels are the reference level of the factor that encodes the exposure variable and the level corresponding to its first dummy variable for \emph{x*} and \emph{x}, respectively.
#' If one wishes to evaluate natural effect components at different reference levels (e.g. if the natural effect model includes mediated interaction, quadratic or higher-order polynomial terms for the exposure; see examples),
#' these can be specified as a vector of the form \code{c(x*,x)} via the \code{xRef} argument.
#'
#' If applicable, covariate levels at which natural effect components are evaluated can also be specified. This is particularly useful for natural effect models encoding effect modification by baseline covariates (e.g. moderated mediation).
#' By default, these levels are set to 0 for continuous covariates and to the reference level for categorical covariates coded as factors.
#' Different covariate levels can be specified via the \code{covLev} argument, which requires a vector including valid levels for covariates that are specified in the natural effect model (or a subset of covariates that are specified as modifiers of either the natural direct or indirect effect or both).
#' Levels need to be preceded by the name of the corresponding covariate, e.g., \code{covLev = c(gender = "M", age = 30)}. Covariates for which the levels are left unspecified are set to their default levels (see examples).
#' The \code{\link{print}} and \code{\link[=summary.neLht]{summary}} functions for \code{neEffdecomp} objects return the covariate levels at which natural effect components are evaluated.
#' No specific levels are returned for covariates that are not specified as modifier since effect decomposition is independent of the level of these covariates (see examples).
#'
#' @name neLht
#' @note \code{neEffdecomp} is internally called by \code{\link{plot.neModel}} to create confidence interval plots for \code{neModel} objects.
#' @seealso \code{\link{plot.neLht}}, \code{\link{neLht-methods}}, \code{\link[multcomp]{glht}}, \code{\link[=coef.glht]{glht-methods}}, \code{\link{neModel}}, \code{\link{plot.neModel}}, \code{\link{summary}}
#' @examples
#' data(UPBdata)
#'
#' impData <- neImpute(UPB ~ att * negaff + gender + educ + age,
#' family = binomial, data = UPBdata)
#' neMod <- neModel(UPB ~ att0 * att1 + gender + educ + age,
#' family = binomial, expData = impData, se = "robust")
#'
#' lht <- neLht(neMod, linfct = c("att0 = 0", "att0 + att0:att1 = 0",
#' "att1 = 0", "att1 + att0:att1 = 0",
#' "att0 + att1 + att0:att1 = 0"))
#' summary(lht)
#'
#' ## or obtain directly via neEffdecomp
#' eff <- neEffdecomp(neMod)
#' summary(eff)
#'
#' ## changing reference levels for multicategorical exposures
#' UPBdata$attcat <- factor(cut(UPBdata$att, 3), labels = c("L", "M", "H"))
#' impData <- neImpute(UPB ~ attcat * negaff + gender + educ + age,
#' family = binomial, data = UPBdata)
#' neMod <- neModel(UPB ~ attcat0 * attcat1 + gender + educ + age,
#' family = binomial, expData = impData, se = "robust")
#'
#' neEffdecomp(neMod)
#' neEffdecomp(neMod, xRef = c("L", "H"))
#' neEffdecomp(neMod, xRef = c("M", "H"))
#'
#'
#' ## changing reference levels for continuous exposures
#' impData <- neImpute(UPB ~ (att + I(att^2)) * negaff + gender + educ + age,
#' family = binomial, data = UPBdata)
#' neMod <- neModel(UPB ~ (att0 + I(att0^2)) * (att1 + I(att1^2)) + gender + educ + age,
#' family = binomial, expData = impData, se = "robust")
#' neEffdecomp(neMod)
#' neEffdecomp(neMod, xRef = c(-1, 0))
#'
#' ## changing covariate levels when allowing for modification
#' ## of the indirect effect by baseline covariates
#' impData <- neImpute(UPB ~ (att + negaff + gender + educ + age)^2,
#' family = binomial, data = UPBdata)
#' neMod <- neModel(UPB ~ att0 * att1 + gender + educ + age + att1:gender + att1:age,
#' family = binomial, expData = impData, se = "robust")
#' neEffdecomp(neMod)
#' neEffdecomp(neMod, covLev = c(gender = "F", age = 0)) # default covariate levels
#' neEffdecomp(neMod, covLev = c(gender = "M", age = 40))
#' neEffdecomp(neMod, covLev = c(gender = "M", age = 40, educ = "L"))
#' neEffdecomp(neMod, covLev = c(gender = "M", age = 40, educ = "M"))
#' neEffdecomp(neMod, covLev = c(gender = "M", age = 40, educ = "H"))
#' # effect decomposition is independent of education level
#' neEffdecomp(neMod, covLev = c(gender = "M"))
#' # age is set to its default level when left unspecified
#'
#' @export
NULL
#' Methods for linear hypotheses in natural effect models
#'
#' @description Obtain confidence intervals and statistical tests for linear hypotheses in natural effect models.
#' @param object an object of class \code{neLht}.
#' @param type the type of bootstrap intervals required. The default \code{"norm"} returns normal approximation bootstrap confidence intervals. Currently, \code{"norm"}, \code{"basic"}, \code{"perc"} and \code{"bca"} are supported (see \code{\link[boot]{boot.ci}}).
#' @param calpha a function computing the critical value. The default \code{univariate_calpha()} returns unadjusted confidence intervals, whereas \code{adjusted_calpha()} returns adjusted confidence intervals.
#' @param test a function for computing p-values. The default \code{univariate()} does not apply a multiple testing correction. The function \code{adjusted()} allows to correct for multiple testing (see \code{\link[multcomp]{summary.glht}} and \code{\link[multcomp]{adjusted}}) and \code{Chisquare()} allows to test global linear hypotheses.
#' @param ... additional arguments.
#' @inheritParams stats::confint.default
#' @name neLht-methods
#' @details
#' \code{confint} yields bootstrap confidence intervals or confidence intervals based on the sandwich estimator (depending on the type of standard errors requested when fitting the \code{\link{neModel}} object).
#' Bootstrap confidence intervals are internally called via the \code{\link[boot]{boot.ci}} function from the \pkg{boot} package.
#' Confidence intervals based on the sandwich estimator are internally called via the corresponding \code{\link[multcomp]{confint.glht}} function from the \pkg{multcomp} package.
#' The default confidence level specified in \code{level} (which corresponds to the \code{conf} argument in \code{\link[boot]{boot.ci}}) is 0.95
#' and the default type of bootstrap confidence interval, \code{"norm"}, is based on the normal approximation.
#' Bias-corrected and accelerated (\code{"bca"}) bootstrap confidence intervals require a sufficiently large number of bootstrap replicates (for more details see \code{\link[boot]{boot.ci}}).
#'
#' A summary table with large sample tests, similar to that for \code{\link[multcomp]{glht}}, can be obtained using \code{summary}.
#'
#' In contrast to \code{\link[multcomp]{summary.glht}}, which by default returns \emph{p}-values that are adjusted for multiple testing,
#' the summary function returns unadjusted \emph{p}-values. Adjusted \emph{p}-values can also be obtained by specifying the \code{test} argument
#' (see \code{\link[multcomp]{adjusted}} for more details).
#'
#' Global Wald tests considering all linear hypotheses simultaneously (i.e. testing the global null hypothesis)
#' can be requested by specifying \code{test = Chisqtest()}.
#'
#' See \code{\link[=coef.glht]{glht-methods}} for additional methods for \code{glht} objects.
#'
#' @note For the bootstrap, \emph{z}-values in the summary table are simply calculated by dividing the parameter estimate by its corresponding bootstrap standard error.
#' Corresponding \emph{p}-values in the summary table are only indicative, since the null distribution for each statistic is assumed to be approximately standard normal.
#' Therefore, whenever possible, it is recommended to focus mainly on bootstrap confidence intervals for inference, rather than the provided \emph{p}-values.
#' @seealso \code{\link{neLht}}, \code{\link{plot.neLht}}, \code{\link[multcomp]{glht}}, \code{\link[=coef.glht]{glht-methods}}
#' @examples
#' data(UPBdata)
#'
#' impData <- neImpute(UPB ~ att * negaff + gender + educ + age,
#' family = binomial, data = UPBdata)
#' neMod <- neModel(UPB ~ att0 * att1 + gender + educ + age,
#' family = binomial, expData = impData, se = "robust")
#'
#' lht <- neLht(neMod, linfct = c("att0 = 0", "att0 + att0:att1 = 0",
#' "att1 = 0", "att1 + att0:att1 = 0",
#' "att0 + att1 + att0:att1 = 0"))
#'
#' ## obtain confidence intervals
#' confint(lht)
#' confint(lht, parm = c("att0", "att0 + att0:att1"))
#' confint(lht, parm = 1:2, level = 0.90)
#'
#' ## summary table
#' summary(lht)
#'
#' ## summary table with omnibus Chisquare test
#' summary(lht, test = Chisqtest())
NULL
#' Confidence interval plots for linear hypotheses in natural effect models
#'
#' @description Confidence interval plots for linear hypotheses in natural effect models.
#' @param x an object of class \code{neLht}.
#' @param ci.type the type of bootstrap intervals required (see \code{type} argument in \code{\link[medflex]{neModel-methods}}).
#' @param transf transformation function to be applied internally on the (linear hypothesis) estimates and their confidence intervals (e.g. \code{exp} for logit or Poisson regression). The default is \code{identity} (i.e. no transformation).
#' @param ylabels character vector containing the labels for the (linear hypothesis) estimates to be plotted on the y-axis.
#' @param yticks.at numeric vector containing the y-coordinates (from 0 to 1) to draw the tick marks for the different estimates and their corresponding confidence intervals.
#' @param ... additional arguments.
#' @inheritParams stats::confint.default
#' @name plot.neLht
#' @details This function is an adapted version of \code{\link[multcomp]{plot.glht}} from the \pkg{multcomp} package and
#' yields confidence interval plots for each of the linear hypothesis parameters.
#' @seealso \code{\link{neModel}}, \code{\link{neLht}}, \code{\link{neEffdecomp}}
#' @examples
#' data(UPBdata)
#'
#' impData <- neImpute(UPB ~ att * negaff + gender + educ + age,
#' family = binomial, data = UPBdata)
#' neMod <- neModel(UPB ~ att0 * att1 + gender + educ + age,
#' family = binomial, expData = impData, se = "robust")
#'
#' lht <- neLht(neMod, linfct = c("att0 = 0", "att0 + att0:att1 = 0",
#' "att1 = 0", "att1 + att0:att1 = 0",
#' "att0 + att1 + att0:att1 = 0"))
#'
#' ## all pairs return identical output
#' plot(confint(lht), transf = exp)
#' plot(lht, transf = exp)
#'
#' plot(neEffdecomp(neMod), transf = exp)
#' plot(neMod, transf = exp)
#'
#' \dontshow{
#' plot(neEffdecomp(neMod), level = 0.8, transf = exp, ylabels = c("PDE", "TDE", "PIE", "TIE", "TE"), yticks.at = c(0, 0.1, 0.5, 0.6, 1))
#' plot(neMod, level = 0.8, transf = exp, ylabels = c("PDE", "TDE", "PIE", "TIE", "TE"), yticks.at = c(0, 0.1, 0.5, 0.6, 1))
#'
#' lht <- neLht(neMod, linfct = c("att0 = 0"))
#' summary(lht)
#' lht <- neLht(neMod, linfct = c("att0 = 0", "att0 + att0:att1 = 2"))
#' summary(lht)
#' }
#' @export
NULL
coef.neLhtCI <- function (object, ...)
{
attr(object, "coef")
}
#' @rdname neLht-methods
#' @export
confint.neLhtBoot <- function (object, parm, level = 0.95, type = "norm", ...)
{
if (missing(parm))
parm <- names(coef(object))
else if (is.numeric(parm))
parm <- names(coef(object))[parm]
extractBootci <- function(index, x, level, type) rev(rev(boot::boot.ci(x,
conf = level, type = type, t0 = object$linfct[index,
] %*% object$model$bootRes$t0, t = as.vector(object$linfct[index,
] %*% t(object$model$bootRes$t)))[[4]])[1:2])
ci <- t(sapply(seq.int(nrow(object$linfct)), extractBootci,
object$model$bootRes, level = level, type = type))
dimnames(ci) <- list(rownames(object$linfct), paste0(100 *
level, c("% LCL", "% UCL")))
ci <- ci[parm, ]
attributes(ci) <- c(attributes(ci), list(level = level, coef = coef(object)[parm],
R = attr(object, "R"), type = type))
class(ci) <- c("neBootCI", "neLhtCI", class(ci))
return(ci)
}
#' @rdname neLht-methods
#' @export
confint.neLht <- function (object, parm, level = 0.95, calpha = univariate_calpha(), ...)
{
class(object) <- c("glht", class(object))
ci <- confint(object, level = level, calpha = calpha, ...)$confint[, c("lwr", "upr")]
dimnames(ci)[[2]] <- paste0(100 * level, c("% LCL", "% UCL"))
ci <- ci[parm, ]
attributes(ci) <- c(attributes(ci), list(level = level, coef = coef(object)[parm], calpha = calpha))
class(ci) <- c("neLhtCI", class(ci))
return(ci)
}
#' @rdname neLht
#' @export
neEffdecomp <- function (model, xRef, covLev, ...)
{
UseMethod("neEffdecomp")
}
#' @rdname neLht
#' @export
neEffdecomp.neModel <- function (model, xRef, covLev, ...)
{
xFact <- is.factor(model$neModelFit$data[, attr(terms(model), "vartype")$Xexp[[1]]])
if (xFact) xRefCheck <- levels(model$neModelFit$data[, attr(terms(model), "vartype")$Xexp[[1]]])
if (missing(xRef)) {
xRef <- if (xFact) xRefCheck[1:2] else c(0, 1)
} else {
if (xFact && !all(xRef %in% xRefCheck)) {
warning(gettextf("Invalid reference levels! Default reference levels %s were used instead.",
paste0("c(", paste(paste0("'", xRefCheck, "'"), collapse = ", "), ")")))
xRef <- xRefCheck[1:2]
}
}
calcContr <- function(x, formula, covDat) {
if (xFact) x <- factor(x, levels = xRefCheck)
dat1 <- if (nrow(covDat)) data.frame(1, x[1], x[2], covDat) else data.frame(1, x[1], x[2])
names(dat1) <- all.vars(formula)
oldVars <- grep("factor\\(", dimnames(attr(terms(formula), "factors"))[[1]], value = TRUE)
if (length(oldVars)) {
newVars <- names(which(sapply(all.vars(formula), grep, oldVars)==TRUE))
tmp <- mgsub(oldVars, newVars, deparse(formula[[3]]), fixed = TRUE)
formula[[3]] <- as.call(parse(text = tmp))[[1]]
} #
modmat1 <- model.matrix(formula, data = dat1)
dat2 <- if (nrow(covDat)) data.frame(1, x[3], x[4], covDat) else data.frame(1, x[3], x[4])
names(dat2) <- all.vars(formula)
modmat2 <- model.matrix(formula, data = dat2)
return(t(modmat1 - modmat2))
}
list <- list(xRef[c(2, 1, 1, 1)],
xRef[c(2, 2, 1, 2)],
xRef[c(1, 2, 1, 1)],
xRef[c(2, 2, 2, 1)],
xRef[c(2, 2, 1, 1)])
form <- stats::formula(model$neModelFit)
vartype <- attr(terms(model), "vartype")
if (is.na(vartype$Y)) vartype$Y <- as.character(form[[2]])
cov <- all.vars(form)[!all.vars(form) %in% unlist(vartype[c("Y", "Xexp")])]
cov <- if(!length(cov)) NULL else cov
varterms <- dimnames(attr(terms(form), "factors"))[[1]][-1]
covTerms <- if(!is.null(cov)) varterms[sapply(cov, grep, varterms)] else NULL
if (identical(cov, covTerms)) {
dat <- quote(model$neModelFit$data)
}
else {
modframe <- model.frame(model$neModelFit, data = model$neModelFit$data)
dat <- quote(modframe)
}
if (!missing(covLev) & !length(cov)) warning("As the natural effect model does not encode covariate effects, specified covariate levels are not taken into account.")
tmp <- attr(terms(form), "factors")[covTerms, which(attr(terms(form), "order") > 1), drop = FALSE]
covModifier <- if (!is.null(tmp)) cov[unlist(sapply(cov, grep, names(which(rowSums(as.matrix(tmp)) > 0))))] else NULL
covClass <- sapply(eval(dat)[, covTerms, drop = FALSE], class)
if (missing(covLev)) {
covLev <- rep(NA, length(cov))
names(covLev) <- cov
}
if (is.null(names(covLev)) & !is.null(cov)) {
warning("Please provide names for the covariates! The specified covariate levels were discarded and default levels were used instead.")
}
else {
if (!all(names(covLev) %in% cov)) warning("For some covariate levels, the corresponding covariate name was either not provided or invalid. These levels were discarded and default levels were used instead.")
}
covLev <- covLev[cov]
covMat <- cbind(covLev, cov, covClass, covTerms)
covList <- split(covMat, 1:nrow(covMat))
lapply(covList, function(x) {
switch(x[3],
"factor" = {if (all(!is.na(x[1]), !x[1] %in% levels(eval(dat)[, x[4]])))
warning(gettextf("Invalid covariate levels for %s! Default levels for this covariate were used instead.", x[2]))},
"numeric" = {if (all(!is.na(x[1]), is.na(suppressWarnings(as.numeric(x[1])))))
warning(gettextf("Invalid covariate levels for %s! Default levels for this covariate were used instead.", x[2]))},
"integer" = {if (all(!is.na(x[1]), is.na(suppressWarnings(as.numeric(x[1])))))
warning(gettextf("Invalid covariate levels for %s! Default levels for this covariate were used instead.", x[2]))})
})
covDat <- as.data.frame(lapply(covList, function(x) {
switch(x[3],
"factor" = {factor(if (all(!is.na(x[1]), x[1] %in% levels(eval(dat)[, x[4]]))) x[1] else levels(eval(dat)[, x[4]])[1],
levels = levels(eval(dat)[, x[4]]))},
"numeric" = {if (all(!is.na(x[1]), !is.na(as.numeric(x[1])))) as.numeric(x[1]) else 0},
"integer" = {if (all(!is.na(x[1]), !is.na(as.numeric(x[1])))) as.numeric(x[1]) else 0})
}))
if (nrow(covDat)) {
covLev <- as.matrix(covDat)
colnames(covLev) <- cov
}
else {
covLev <- NULL
}
K2 <- t(data.frame(lapply(list, calcContr, form, covDat)))
K2 <- unique(K2)
colnames(K2) <- names(coef(model)) #
rownames <- if (nrow(K2) == 3) {
c("natural direct effect", "natural indirect effect", "total effect")
} else {
c("pure direct effect", "total direct effect", "pure indirect effect", "total indirect effect", "total effect")
}
K <- matrix(0, nrow = nrow(K2), ncol = length(coef(model)), dimnames = list(rownames, names(coef(model))))
K[, colnames(K2)] <- K2
colnames(K) <- NULL
effdecomp <- neLht(model, linfct = K)
class(effdecomp) <- c("neEffdecomp", class(effdecomp))
attributes(effdecomp) <- c(attributes(effdecomp), list(xRef = xRef, covLev = covLev, covModifier = covModifier))
return(effdecomp)
}
#' @rdname neLht
#' @export
neLht <- function (model, ...)
{
UseMethod("neLht")
}
#' @rdname neLht
#' @export
neLht.neModel <- function (model, ...)
{
lht <- multcomp::glht(model, ...)
if (inherits(model, "neModelBoot")) attr(lht, "R") <- model$bootRes$R
class(lht) <- c(if (inherits(model, "neModelBoot")) "neLhtBoot", "neLht", class(lht))
return(lht)
}
#' @rdname plot.neLht
#' @export
plot.neEffdecomp <- function (x, level = 0.95, transf = identity,
ylabels, yticks.at, ...)
{
args <- as.list(match.call())
args[["x"]] <- quote(x)
if (nrow(x$linfct) == 5)
if (missing(yticks.at))
args$yticks.at <- c(0, 0.15, 0.5, 0.65, 1)
else if (missing(yticks.at))
args$yticks.at <- NULL
args[[1]] <- if (inherits(x, "neLhtBoot")) substitute(plot.neLhtBoot) else substitute(plot.neLht)
eval(as.call(args))
}
#' @rdname plot.neLht
#' @export
plot.neLht <- function (x, level = 0.95, transf = identity, ylabels,
yticks.at, ...)
{
args <- as.list(match.call())[-1L]
args <- c(substitute(confint), object = substitute(x),
args[names(args) %in% names(formals(confint.neLhtBoot))])
confint <- eval(as.call(args))
plot(confint, transf = transf, ylabels = ylabels, yticks.at = yticks.at,
...)
}
#' @rdname plot.neLht
#' @export
plot.neLhtBoot <- function (x, level = 0.95, ci.type = "norm", transf = identity,
ylabels, yticks.at, ...)
{
args <- as.list(match.call())[-1L]
args <- c(substitute(confint), object = substitute(x), type = ci.type,
args[names(args) %in% names(formals(confint.neLhtBoot))])
confint <- eval(as.call(args))
plot(confint, transf = transf, ylabels = ylabels, yticks.at = yticks.at,
...)
}
#' @export
plot.neLhtCI <- function (x, transf = identity, ylabels, yticks.at, main, xlab = NULL,
ylab = NULL, xlim, ylim, mar, mai, ...)
{
args <- as.list(match.call())[-1L]
if (!grep("confint", args$x) == 1) {
transf <- eval(args$x[[1]])
args$x <- args$x[[-1]]
x <- eval(args$x)
}
ci <- transf(x)
xrange <- c(min(ci[, 1]), max(ci[, 2]))
yvals <- yticks.at <- if (missing(yticks.at))
nrow(ci):1
else (nrow(ci) - 1) * (1 - yticks.at) + 1
if (missing(ylabels))
ylabels <- dimnames(ci)[[1]]
old.par <- par(no.readonly = TRUE)
if (all(missing(mai), missing(mar))) {
mar <- old.par$mar
mar[2] <- (max(strwidth(ylabels, "inch")) + 0.4) * (old.par$mar/old.par$mai)[1]
}
else if (missing(mar)) {
mar <- mai * (old.par$mar/old.par$mai)[1]
}
par(mar = mar)
null <- transf(0)
tmp.range <- c(min(null, xrange[1]), max(null, xrange[2]))
tmp.range <- mean(tmp.range) + c(-1, 1) * 0.6 * diff(tmp.range)
if (missing(xlab))
xlab <- ""
if (missing(ylab))
ylab <- ""
if (missing(xlim))
xlim <- tmp.range
if (missing(ylim))
ylim <- c(0.5, nrow(ci) + 0.5)
if (missing(main))
main <- paste0(100 * attr(x, "level"), if (inherits(x, "neBootCI")) "% bootstrap CIs" else "% sandwich CIs")
plot(c(ci[, 1], ci[, 2]), rep.int(yvals, 2), type = "n",
main = main, axes = FALSE, xlab = xlab, ylab = ylab,
xlim = xlim, ylim = ylim, ...)
axis(1, las = 1, ...)
axis(2, at = yvals, labels = ylabels, las = 1, ...)
abline(v = null, lty = 2, lwd = 1, ...)
left <- ci[, 1]
left[!is.finite(left)] <- min(c(0, xlim[1] * 2))
right <- ci[, 2]
right[!is.finite(right)] <- max(c(0, xlim[2] * 2))
segments(left, yvals, right, yvals, ...)
points(transf(coef(x)), yvals, pch = 20, ...)
box()
par(mar = old.par$mar, mai = old.par$mai)
}
#' @method print neLht
#' @export
print.neLht <- function (x, digits = max(3, getOption("digits") - 3), ...)
{
if (inherits(x, "neEffdecomp")) {
cat("Effect decomposition on the scale of the linear predictor\n---\n")
covModifier <- dimnames(attr(x, "covLev"))[[2]] %in% attr(x, "covModifier")
sep <- if (all(covModifier) | !any(covModifier)) "" else ", "
if (!is.null(attr(x, "covLev"))) cat("conditional on:", paste(paste(dimnames(attr(x, "covLev")[, covModifier, drop = FALSE])[[2]], attr(x, "covLev")[, covModifier, drop = FALSE], sep = " = ", collapse = ", "),
paste(dimnames(attr(x, "covLev")[, !covModifier, drop = FALSE])[[2]], collapse = ", "), sep = sep), "\n")
cat(paste0("with x* = ", attr(x, "xRef")[1], ", x = ", attr(x, "xRef")[2]), "\n---\n")
}
else cat("Linear hypotheses for natural effect models\n---\n")
coef <- as.matrix(coef(x))
dimnames(coef)[[2]] <- "Estimate"
print(coef, digits = digits, ...)
}
#' @method print neLhtCI
#' @export
print.neLhtCI <- function (x, ...)
{
adj <- attr(attr(x, "calpha"), "type")
attributes(x)[c("level", "coef", "class", "calpha")] <- NULL
print.default(x)
switch(adj,
"univariate" = cat("---\nconfidence intervals\nbased on the sandwich estimator\n\n"),
"adjusted" = cat("---\nadjusted confidence intervals\nbased on the sandwich estimator\n\n"))
}
#' @method print summary.neLht
#' @export
print.summary.neLht <- function (x, digits = max(3, getOption("digits") - 3), ...)
{
catSE <- if (inherits(x, "summary.neLhtBoot")) "with standard errors based on the non-parametric bootstrap\n---\n"
else "with standard errors based on the sandwich estimator\n---\n"
if (inherits(x$test, "mtest")) {
if (inherits(x, "summary.neEffdecomp")) {
cat("Effect decomposition on the scale of the linear predictor\n", catSE, sep = "")
covModifier <- dimnames(attr(x, "covLev"))[[2]] %in% attr(x, "covModifier")
sep <- if (all(covModifier) | !any(covModifier)) "" else ", "
if (!is.null(attr(x, "covLev"))) cat("conditional on:", paste(paste(dimnames(attr(x, "covLev")[, covModifier, drop = FALSE])[[2]], attr(x, "covLev")[, covModifier, drop = FALSE], sep = " = ", collapse = ", "),
paste(dimnames(attr(x, "covLev")[, !covModifier, drop = FALSE])[[2]], collapse = ", "), sep = sep), "\n")
cat(paste0("with x* = ", attr(x, "xRef")[1], ", x = ", attr(x, "xRef")[2]), "\n---\n")
}
else {
cat("Linear hypotheses for natural effect models\n", catSE, sep = "")
}
if (!identical(x$rhs, rep(0, length(x$rhs))))
dimnames(x$coefficients)[[1]] <- paste(dimnames(x$coefficients)[[1]],
"=", x$rhs)
printCoefmat(x$coefficients, digits = digits, has.Pvalue = TRUE,
P.values = TRUE)
switch(x$test$type, univariate = cat("(Univariate p-values reported)"),
`single-step` = cat("(Adjusted p-values reported -- single-step method)"),
Shaffer = cat("(Adjusted p-values reported -- Shaffer method)"),
Westfall = cat("(Adjusted p-values reported -- Westfall method)"),
cat("(Adjusted p-values reported --", x$test$type,
"method)"))
cat("\n\n")
}
else if (inherits(x$test, "gtest")) {
cat("Global linear hypothesis test for natural effect models\n",
catSE, sep = "")
pr <- data.frame(x$test$SSH, x$test$df[1], x$test$pval)
names(pr) <- c("Chisq", "DF", "Pr(>Chisq)")
print(pr, digits = digits, ...)
}
}
#' @rdname neLht-methods
#' @method summary neLht
#' @export
summary.neLht <- function (object, test = univariate(), ...)
{
class(object) <- c("glht", class(object))
summary <- summary(object, test = test, ...)
pq <- summary$test
if (inherits(pq, "mtest")) {
coef.table <- cbind(pq$coefficients, pq$sigma, pq$tstat,
pq$pvalues)
dimnames(coef.table) <- list(names(coef(object)), c("Estimate",
"Std. Error", "z value", "Pr(>|z|)"))
summary$coefficients <- coef.table
}
class(summary) <- c(if (inherits(object, "neEffdecomp")) "summary.neEffdecomp",
if (inherits(object, "neLhtBoot")) "summary.neLhtBoot", "summary.neLht")
return(summary)
}
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.