Nothing
###############################################################################
##
#' @title Contrasts for lm, glm, lme, and geeglm objects
#' @description Computes linear functions (i.e. weighted sums) of the
#' estimated regression parameters. Can also test the hypothesis,
#' that such a function is equal to a specific value.
#' @name esticon
##
###############################################################################
#'
## #' @aliases esticon.lm esticon.gls
#'
#' @details Let the estimated parameters of the model be
#' \deqn{\beta_1, \beta_2, \dots, \beta_p}
#'
#' A linear function of the estimates is of the form \deqn{l=\lambda_1
#' \beta_1+\lambda_2 \beta_2+ \dots+\lambda_p \beta_p} where
#' \eqn{\lambda_1, \lambda_2, \dots,\lambda_p} is specified by the
#' user.
#'
#' The esticon function calculates l, its standard error and by default also a
#' 95 pct confidence interval. It is sometimes of interest to test the
#' hypothesis \eqn{H_0: l=\beta_0} for some value \eqn{\beta_0}
#' given by the user. A test is provided for the hypothesis \eqn{H_0:
#' l=0} but other values of \eqn{\beta_0} can be specified.
#'
#' In general, one can specify r such linear functions at one time by
#' specifying L to be an \eqn{r\times p} matrix where each row consists
#' of p numbers \eqn{\lambda_1,\lambda_2,\dots, \lambda_p}. Default is
#' then that \eqn{\beta_0} is a p vector of 0s but other values can be
#' given.
#'
#' It is possible to test simultaneously that all specified linear functions
#' are equal to the corresponding values in \eqn{\beta_0}.
#'
#' For computing contrasts among levels of a single factor, 'contrast.lm' may
#' be more convenient.
#'
#' @param obj Regression object (of type lm, glm, lme, geeglm).
## #' @param x A linear contrast object (as returned by \code{esticon()}.
#' @param L Matrix (or vector) specifying linear functions of the regression
#' parameters (one
#' linear function per row). The number of columns must match the number of
#' fitted regression parameters in the model. See 'details' below.
#' @param parm a specification of which parameters are to be given
#' confidence intervals, either a vector of numbers or a vector
#' of names. If missing, all parameters are considered.
#' @param beta0 A vector of numbers
#' @param conf.int TRUE
## #' @param conf.level The desired confidence level.
#' @param level The confidence level
#' @param joint.test Logical value. If TRUE a 'joint' Wald test for the
#' hypothesis L beta = beta0 is made. Default is that the 'row-wise' tests are
#' made, i.e. (L beta)i=beta0i. If joint.test is TRUE, then no confidence
#' interval etc. is calculated.
#' @param \dots Additional arguments; currently not used.
#'
#' @return Returns a matrix with one row per linear function. Columns contain
#' estimated coefficients, standard errors, t values, degrees of freedom,
#' two-sided p-values, and the lower and upper endpoints of the 1-alpha
#' confidence intervals.
#'
#' @author Søren Højsgaard, \email{sorenh@@math.aau.dk}
#' @keywords utilities
#' @examples
#'
#' data(iris)
#' lm1 <- lm(Sepal.Length ~ Sepal.Width + Species + Sepal.Width : Species, data=iris)
#' ## Note that the setosa parameters are set to zero
#' coef(lm1)
#'
#' ## Estimate the intercept for versicolor
#' lambda1 <- c(1, 0, 1, 0, 0, 0)
#' esticon(lm1, L=lambda1)
#'
#' ## Estimate the difference between versicolor and virgica intercept
#' ## and test if the difference is 1
#' lambda2 <- c(0, 1, -1, 0, 0, 0)
#' esticon(lm1, L=lambda2, beta0=1)
#'
#' ## Do both estimates at one time
#' esticon(lm1, L=rbind(lambda1, lambda2), beta0=c(0, 1))
#'
#' ## Make a combined test for that the difference between versicolor and virgica intercept
#' ## and difference between versicolor and virginica slope is zero:
#' lambda3 <- c(0, 0, 0, 0, 1, -1)
#' esticon(lm1, L=rbind(lambda2, lambda3), joint.test=TRUE)
#'
#' # Example using esticon on coxph objects (thanks to Alessandro A. Leidi).
#' # Using dataset 'veteran' in the survival package
#' # from the Veterans' Administration Lung Cancer study
#'
#' if (require(survival)){
#' data(veteran)
#' sapply(veteran, class)
#' levels(veteran$celltype)
#' attach(veteran)
#' veteran.s <- Surv(time, status)
#' coxmod <- coxph(veteran.s ~ age + celltype + trt, method='breslow')
#' summary(coxmod)
#'
#' # compare a subject 50 years old with celltype 1
#' # to a subject 70 years old with celltype 2
#' # both subjects on the same treatment
#' AvB <- c(-20, -1, 0, 0, 0)
#'
#' # compare a subject 40 years old with celltype 2 on treat=0
#' # to a subject 35 years old with celltype 3 on treat=1
#' CvB <- c(5, 1, -1, 0, -1)
#'
#' est <- esticon(coxmod, L=rbind(AvB, CvB))
#' est
#' ##exp(est[, c(2, 7, 8)])
#' }
#' @export
esticon <- function(obj, L, beta0, conf.int = TRUE, level=0.95, joint.test=FALSE,...)
UseMethod("esticon")
#' @export
esticon.gls <- function (obj, L, beta0, conf.int = TRUE, level=0.95, joint.test=FALSE,...){
if (joint.test) .wald(obj, L, beta0)
else {
stat.name <- "X2.stat"
##vcv <- vcov(obj)
vcv <- vcov(obj, complete=FALSE)
coef.mat <- matrix(coef(obj))
df <- 1
.esticonCore(obj, L, beta0, conf.int=conf.int,level,coef.mat,vcv,df,stat.name)
}
}
#' @export
esticon.geeglm <- function (obj, L, beta0, conf.int = TRUE, level=0.95, joint.test=FALSE,...){
if (joint.test) .wald(obj, L, beta0)
else {
stat.name <- "X2.stat"
coef.mat <- summary(obj)$coef
vcv <- summary(obj)$cov.scaled
df <- 1
.esticonCore(obj, L, beta0, conf.int=conf.int,level,coef.mat,vcv,df,stat.name)
}
}
#' @export
esticon.lm <- function (obj, L, beta0, conf.int = TRUE, level=0.95, joint.test=FALSE,...){
if (joint.test) .wald(obj, L, beta0)
else {
stat.name <- "t.stat"
coef.mat <- summary.lm(obj)$coefficients
coef.vec <- coef(obj)
vcv <- summary.lm(obj)$cov.unscaled * summary.lm(obj)$sigma^2
df <- obj$df.residual
.esticonCore(obj, L, beta0, conf.int=conf.int, level, coef.mat, vcv, df, stat.name, coef.vec=coef.vec)
}
}
#' @export
esticon.glm <- function (obj, L, beta0, conf.int = TRUE, level=0.95, joint.test=FALSE,...){
if (joint.test) .wald(obj, L, beta0)
else {
coef.mat <- summary.lm(obj)$coefficients
vcv <- summary(obj)$cov.scaled
if(family(obj)[1] %in% c("poisson", "binomial")){
stat.name <- "X2.stat"
df <- 1
} else {
stat.name <- "t.stat"
df <- obj$df.residual
}
.esticonCore(obj, L, beta0, conf.int=conf.int,level=level,coef.mat,vcv,df,stat.name)
}
}
#' @export
esticon.merMod <- function (obj, L, beta0, conf.int = TRUE, level=0.95, joint.test=FALSE, ...){
if (joint.test) .wald(obj, L, beta0)
else {
stat.name <- "X2.stat"
coef.mat <- matrix(lme4::fixef(obj))
##vcv <- as.matrix(vcov(obj))
vcv <- as.matrix(vcov(obj, complete=FALSE))
df <- 1
.esticonCore(obj, L, beta0, conf.int=conf.int, level, coef.mat, vcv, df, stat.name)
}
}
#' @export
esticon.coxph <-
function (obj, L, beta0, conf.int = TRUE, level = 0.95, joint.test = FALSE, ...){
if (joint.test == TRUE) .wald(obj, L, beta0)
else {
cf <- summary(obj)$coefficients
vcv <- obj$var
stat.name <- "X2.stat"
df <- 1
.esticonCore(obj, L, beta0, conf.int = conf.int, level = level,
cf, vcv, df, stat.name)
}
}
### ######################################################
###
### esticon.lme needs better testing at some point
###
### ######################################################
#' @export
esticon.lme <- function (obj, L, beta0, conf.int = NULL, level=0.95, joint.test=FALSE,...){
warning("The esticon function has not been thoroughly teste on 'lme' objects")
if (joint.test) .wald(obj, L, beta0)
else {
stat.name <- "t.stat"
coef.mat <- summary(obj)$tTable
rho <- summary(obj)$cor
vcv <- rho * outer(coef.mat[, 2], coef.mat[, 2])
tmp <- L
tmp[tmp == 0] <- NA
df.all <- t(abs(t(tmp) * obj$fixDF$X))
df <- apply(df.all, 1, min, na.rm = TRUE)
problem <- apply(df.all != df, 1, any, na.rm = TRUE)
if (any(problem))
warning(paste("Degrees of freedom vary among parameters used to ",
"construct linear contrast(s): ",
paste((1:nrow(tmp))[problem],
collapse = ","),
". Using the smallest df among the set of parameters.",
sep = ""))
df <- min(df)
.esticonCore(obj, L, beta0, conf.int=conf.int,level,coef.mat,vcv,df,stat.name)
}
}
### .functions below here ###
.wald <- function (obj, L, beta0)
{
if (!is.matrix(L) && !is.data.frame(L))
L <- matrix(L, nrow = 1)
if (missing(beta0))
beta0 <- rep(0, nrow(L))
df <- nrow(L)
if (inherits(obj, "geese")){
coef.mat <- obj$beta
vcv <- obj$vbeta
} else if (inherits(obj, "geeglm")){
coef.mat <- obj$coef
vcv <- summary(obj)$cov.scaled
} else if (inherits(obj, "gls")) {
##vcv <- vcov(obj)
vcv <- vcov(obj, complete=FALSE)
coef.mat <- matrix(coef(obj))
} else if (inherits(obj, "gee")) {
coef.mat <- obj$coef
vcv <- obj$robust.variance
}
else if (inherits(obj, "lm")) {
coef.mat <- summary.lm(obj)$coefficients[, 1]
vcv <- summary.lm(obj)$cov.unscaled * summary.lm(obj)$sigma^2
if (inherits(obj, "glm")) {
vcv <- summary(obj)$cov.scaled
}
}
else if (inherits(obj, "coxph")) {
coef.mat <- obj$coef
vcv <- obj$var
}
else
stop("obj must be of class 'lm', 'glm', 'aov', 'gls', 'gee', 'geese', 'coxph'")
u <- (L %*% coef.mat)-beta0
vcv.u <- L %*% vcv %*% t(L)
W <- t(u) %*% solve(vcv.u) %*% u
prob <- 1 - pchisq(W, df = df)
out <- as.data.frame(cbind(W, df, prob))
names(out) <- c("X2.stat", "DF", "Pr(>|X^2|)")
as.data.frame(out)
}
.esticonCore <- function (obj, L, beta0, conf.int = NULL, level, coef.mat,
vcv, df, stat.name, coef.vec=coef.mat[,1]) {
## Notice
## coef.mat: summary(obj)$coefficients
## coef.vec: coef(obj)
## cl <- match.call(); print(cl); print(coef.mat)
if (missing(L)) stop("Contrast matrix 'L' is missing")
if (!is.matrix(L) && !is.data.frame(L))
L <- matrix(L, nrow = 1)
if (missing(beta0))
beta0 <- rep(0, nrow(L))
##print(list(L=L, beta0=beta0))
idx <- !is.na(coef.vec) ## Only want columns of L for identifiable parameters
L <- L[ , idx, drop=FALSE]
if (!dim(L)[2] == dim(coef.mat)[1])
stop(paste("\n Dimension of ",
deparse(substitute(L)),
": ", paste(dim(L), collapse = "x"),
", not compatible with no of parameters in ",
deparse(substitute(obj)), ": ", dim(coef.mat)[1], sep = ""))
ct <- L %*% coef.mat[, 1]
ct.diff <- L %*% coef.mat[, 1] - beta0
vcv.L <- L %*% vcv %*% t(L)
if (is.null(vn <- rownames(L)))
vn <- 1:nrow(L)
rownames(vcv.L) <- colnames(vcv.L) <- vn
vc <- sqrt(diag(vcv.L))
switch(stat.name,
t.stat = {
prob <- 2 * (1 - pt(abs(ct.diff/vc), df))
},
X2.stat = {
prob <- 1 - pchisq((ct.diff/vc)^2, df = 1)
})
if (stat.name == "X2.stat") {
out <- cbind(hyp=beta0, est = ct, stderr = vc, t.value = (ct.diff/vc)^2,
df = df, prob = prob )
}
else if (stat.name == "t.stat") {
out <- cbind(hyp=beta0, est = ct, stderr = vc, t.value = ct.diff/vc,
df = df, prob = prob)
}
dim.names <- list(NULL, c("beta0","estimate","std.error",
"statistic","df","p.value"))
dimnames(out) <- dim.names
out <- out[, c(2,3,4,6,1,5), drop=FALSE]
conf.int <- "wald"
if (!is.null(conf.int)) {
if (level <= 0 || level >= 1)
stop("level should be betweeon 0 and 1. Usual values are 0.95, 0.90")
alpha <- 1 - level
switch(stat.name,
t.stat = { quant <- qt(1 - alpha/2, df) },
X2.stat = { quant <- qnorm(1 - alpha/2) })
cint <- cbind(ct.diff - vc * quant, ct.diff + vc * quant)
colnames(cint) <- c("lwr", "upr")
out <- cbind(out, cint)
}
out <- as.data.frame(out)
## FIXME esticon_class added; not sure if this is good idea?
class(out) <- c("esticon_class", "data.frame")
attr(out, "L") <- L
attr(out, "vcv") <- vcv.L
out
}
#' @rdname esticon
#' @param object An \code{esticon_class} object.
#' @export
coef.esticon_class <- function (object, ...) {
out <- object$estimate
names(out) <- rownames(object)
out
}
#' @export
#' @rdname esticon
summary.esticon_class <- function (object, ...)
{
cat("Coefficients:\n")
##printCoefmat(object$coef)
printCoefmat(object)
cat("\n")
cat("L:\n")
##print(object$L)
print(attr(object, "L"))
cat("\n")
invisible(object)
}
#' @export
print.esticon_class <- function(x, ...){
printCoefmat(x[,1:6])
}
#' @export
#' @rdname esticon
confint.esticon_class <- function (object, parm, level = 0.95, ...)
{
cf <- coef(object)
pnames <- names(cf)
if (missing(parm))
parm <- pnames
else if (is.numeric(parm))
parm <- pnames[parm]
a <- (1 - level)/2
a <- c(a, 1 - a)
## stats:::confint.default code
## pct <- stats:::format.perc(a, 3)
## fac <- qnorm(a)
## replaced with
pct <- a
DF <- object$df
fac <- if (!is.null(DF)) qt(a, DF[1])
else fac <- qnorm(a)
## to here
ci <- array(NA, dim = c(length(parm), 2L), dimnames = list(parm,
pct))
ses <- sqrt(diag(vcov(object)))[parm]
##str(list(cf=cf, parm=parm, fac=fac, ses=ses))
ci[] <- cf[parm] + ses %o% fac
ci
}
#' @export
#' @rdname esticon
vcov.esticon_class <- function (object, ...){
attr(object, "vcv")
}
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.