Nothing
#' Compute and test arbitrary contrasts for regression objects
#'
#' Compute and test arbitrary contrasts for regression objects.
#'
#' Computes the specified contrast(s) by re-fitting the model with the
#' appropriate arguments. A contrast of the form `c(1,0,0,-1)` would
#' compare the mean of the first group with the mean of the fourth group.
#'
#' @aliases fit.contrast fit.contrast.lm fit.contrast.lme
#' @param model regression (lm,glm,aov,lme) object for which the contrast(s)
#' will be computed.
#' @param varname variable name
#' @param coeff vector or matrix specifying contrasts (one per row).
#' @param showall return all regression coefficients. If `TRUE`, all model
#' cofficients will be returned. If `FALSE` (the default), only the
#' coefficients corresponding to the specified contrast will be returned.
#' @param conf.int numeric value on (0,1) or NULL. If a numeric value is
#' specified, confidence intervals with nominal coverage probability
#' `conf.int` will be computed. If `NULL`, confidence intervals will
#' not be computed.
#' @param df boolean indicating whether to return a column containing the
#' degrees of freedom.
#' @param \dots optional arguments provided by methods.
#' @return Returns a matrix containing estimated coefficients, standard errors,
#' t values, two-sided p-values. If `df` is TRUE, an additional column
#' containing the degrees of freedom is included. If `conf.int` is
#' specified lower and upper confidence limits are also returned.
#' @author Gregory R. Warnes \email{greg@@warnes.net}
#' @seealso
#' * [stats::lm()], [stats::contrasts()], [stats::contr.treatment()], [stats::contr.poly()],
#' * Computation and testing of General Linear Hypothesis: [glh.test()],
#' * Computation and testing of estimable functions of model coefficients: [estimable()], [make.contrasts()]
#' @references Venables & Ripley, Section 6.2
#' @keywords models regression
#' @examples
#'
#' set.seed(42)
#'
#' y <- rnorm(100)
#' x <- cut(rnorm(100, mean=y, sd=0.25),c(-4,-1.5,0,1.5,4))
#' reg <- lm(y ~ x)
#' summary(reg)
#'
#' # look at the group means
#' gm <- sapply(split(y,x),mean)
#' gm
#'
#'
#' # mean of 1st group vs mean of 4th group
#' fit.contrast(reg, x, c( 1, 0, 0, -1) )
#' # estimate should be equal to:
#' gm[1] - gm[4]
#'
#' # mean of 1st and 2nd groups vs mean of 3rd and 4th groups
#' fit.contrast(reg, x, c( -1/2, -1/2, 1/2, 1/2) )
#' # estimate should be equal to:
#' sum(-1/2*gm[1], -1/2*gm[2], 1/2*gm[3], 1/2*gm[4])
#'
#' # mean of 1st group vs mean of 2nd, 3rd and 4th groups
#' fit.contrast(reg, x, c( -3/3, 1/3, 1/3, 1/3) )
#' # estimate should be equal to:
#' sum(-3/3*gm[1], 1/3*gm[2], 1/3*gm[3], 1/3*gm[4])
#'
#' # all at once
#' cmat <- rbind( "1 vs 4" =c(-1, 0, 0, 1),
#' "1+2 vs 3+4"=c(-1/2,-1/2, 1/2, 1/2),
#' "1 vs 2+3+4"=c(-3/3, 1/3, 1/3, 1/3))
#' fit.contrast(reg,x,cmat)
#'
#' #
#' x2 <- rnorm(100,mean=y,sd=0.5)
#' reg2 <- lm(y ~ x + x2 )
#' fit.contrast(reg2,x,c(-1,0,0,1))
#'
#' #
#' # Example for Analysis of Variance
#' #
#'
#' set.seed(03215)
#' Genotype <- sample(c("WT","KO"), 1000, replace=TRUE)
#' Time <- factor(sample(1:3, 1000, replace=TRUE))
#' y <- rnorm(1000)
#' data <- data.frame(y, Genotype, Time)
#'
#'
#' # Compute Contrasts & obtain 95% confidence intervals
#'
#' model <- aov( y ~ Genotype + Time + Genotype:Time, data=data )
#'
#' fit.contrast( model, "Genotype", rbind("KO vs WT"=c(-1,1) ), conf=0.95 )
#'
#' fit.contrast( model, "Time",
#' rbind("1 vs 2"=c(-1,1,0),
#' "2 vs 3"=c(0,-1,1)
#' ),
#' conf=0.95 )
#'
#'
#' cm.G <- rbind("KO vs WT"=c(-1,1) )
#' cm.T <- rbind("1 vs 2"=c(-1,1,0),
#' "2 vs 3"=c(0,-1,1) )
#'
#' # Compute contrasts and show SSQ decompositions
#'
#' model <- aov( y ~ Genotype + Time + Genotype:Time, data=data,
#' contrasts=list(Genotype=make.contrasts(cm.G),
#' Time=make.contrasts(cm.T) )
#' )
#'
#' summary(model, split=list( Genotype=list( "KO vs WT"=1 ),
#' Time = list( "1 vs 2" = 1,
#' "2 vs 3" = 2 ) ) )
#'
#'
#' # example for lme
#' library(nlme)
#' data(Orthodont)
#' fm1 <- lme(distance ~ Sex, data = Orthodont,random=~1|Subject)
#'
#' # Contrast for sex. This example is equivalent to standard treatment
#' # contrast.
#' #
#' fit.contrast(fm1, "Sex", c(-1,1), conf.int=0.95 )
#' #
#' # and identical results can be obtained using lme built-in 'intervals'
#' #
#' intervals(fm1)
#'
#' # Cut age into quantile groups & compute some contrasts
#' Orthodont$AgeGroup <- gtools::quantcut(Orthodont$age)
#' fm2 <- lme(distance ~ Sex + AgeGroup, data = Orthodont,random=~1|Subject)
#' #
#' fit.contrast(fm2, "AgeGroup", rbind("Linear"=c(-2,-1,1,2),
#' "U-Shaped"=c(-1,1,1,-1),
#' "Change-Point at 11"=c(-1,-1,1,1)),
#' conf.int=0.95)
#'
#'
#' @export
fit.contrast <- function(model, varname, coeff, showall, conf.int, df, ...)
UseMethod("fit.contrast")
#' @exportS3Method stats::coef
coef.fit_contrast <- function(object, ...)
object
#' @exportS3Method base::print
print.fit_contrast <- function(x, ...)
print(unclass(x))
#' @exportS3Method gmodels::fit.contrast
#' @importFrom stats coef
#' @importFrom stats pt
#' @importFrom stats qt
#' @importFrom stats summary.glm
#' @importFrom stats summary.lm
fit.contrast.lm <- function(model,
varname,
coeff,
showall=FALSE,
conf.int=NULL,
df=FALSE,
...)
{
# check class of model
if( !(any(class(model) %in% c("lm", "aov", "lme") ) ))
stop("contrast.lm can only be applied to objects inheriting from 'lm'",
"and 'lme' (eg: lm,glm,aov,lme).")
# make sure we have the NAME of the variable
if(!is.character(varname))
varname <- deparse(substitute(varname))
# make coeff into a matrix
if(!is.matrix(coeff))
{
coeff <- matrix(coeff, nrow=1)
}
# make sure columns are labeled
if (is.null(rownames(coeff)))
{
rn <- vector(length=nrow(coeff))
for(i in 1:nrow(coeff))
rn[i] <- paste(" c=(",paste(coeff[i,],collapse=" "), ")")
rownames(coeff) <- rn
}
# now convert into the proper form for the contrast matrix
cmat <- make.contrasts(coeff, ncol(coeff) )
cn <- paste(" C",1:ncol(cmat),sep="")
cn[1:nrow(coeff)] <- rownames(coeff)
colnames(cmat) <- cn
# recall fitting method with the specified contrast
m <- model$call
if(is.null(m$contrasts))
m$contrasts <- list()
m$contrasts[[varname]] <- cmat
r <- eval(m, parent.frame())
# now return the correct elements ....
if( 'lme' %in% class(model) )
{
est <- r$coefficients$fixed
se <- sqrt(diag(r$varFix))
tval <- est/se
df.lme <- r$fixDF$X
retval <- cbind(
"Estimate"= est,
"Std. Error"= se,
"t-value"= tval,
"Pr(>|t|)"= 2 * (1 - pt(abs(tval), df.lme)),
"DF"=df.lme
)
}
else if('glm' %in% class(model))
{
smodel <- summary.glm(r)
retval <- cbind(coef(smodel), "DF"=smodel$df[2])
}
else # lm, aov
{
smodel <- summary.lm(r)
retval <- cbind(coef(smodel), "DF"=smodel$df[2])
}
if( !showall )
{
rn <- paste(varname,rownames(coeff),sep="")
ind <- match(rn,rownames(retval))
retval <- retval[ind,,drop=FALSE]
}
if(!missing(conf.int) && !is.null(conf.int)) # add confidence intervals
{
alpha <- 1-conf.int
retval <- cbind( retval,
"lower CI"=retval[,1] -
qt(1-alpha/2,retval[,5])*retval[,2],
"upper CI"=retval[,1] +
qt(1-alpha/2,retval[,5])*retval[,2] )
}
if(!df)
retval <- retval[,-5,drop=FALSE]
class(retval) <- "fit_contrast"
retval
}
# fit.contrast.lme and fit.contrast.mer are necessary because
# 'lme' and 'mer' objects do not inherit from 'lm'.
#
# **Make sure that the argument list *exactly* matches the one
# for fit.contrast.lm() above.**
#
#' @exportS3Method gmodels::fit.contrast
fit.contrast.lme <- function(model, varname, coeff, showall=FALSE,
conf.int=NULL, df=FALSE, ...)
{
fit.contrast.lm(model, varname, coeff, showall, conf.int, df)
}
## # I made rather dramatic changes here and do all calculations in fit.contrast.mer rather than
## # fit.contrast.lm because of the simulation extras ... added sim.mer and n.sim to the parameter list
## fit.contrast.mer <- function(model, varname, coeff, showall=FALSE,
## conf.int=NULL, sim.mer=TRUE, n.sim=1000, ...)
## {
## require(lme4)
## # make sure we have the NAME of the variable
## if(!is.character(varname))
## varname <- deparse(substitute(varname))
## # make coeff into a matrix
## if(!is.matrix(coeff))
## {
## coeff <- matrix(coeff, nrow=1)
## }
## # make sure columns are labeled
## if (is.null(rownames(coeff)))
## {
## rn <- vector(length=nrow(coeff))
## for(i in 1:nrow(coeff))
## rn[i] <- paste(" c=(",paste(coeff[i,],collapse=" "), ")")
## rownames(coeff) <- rn
## }
## # now convert into the proper form for the contrast matrix
## cmat <- make.contrasts(coeff, ncol(coeff) )
## cn <- paste(" C",1:ncol(cmat),sep="")
## cn[1:nrow(coeff)] <- rownames(coeff)
## colnames(cmat) <- cn
## m <- model@call
## if(is.null(m$contrasts))
## m$contrasts <- list()
## m$contrasts[[varname]] <- cmat
## if(is.R())
## r <- eval(m, parent.frame())
## else
## r <- eval(m)
## # now return the correct elements ....
## r.effects <- fixef(r)
## n <- length(r.effects)
## if(sim.mer)
## {
## retval <- est.mer(obj = r, cm = diag(n), beta0 = rep(0, n),
## conf.int = conf.int, show.beta0 = FALSE,
## n.sim=n.sim)
## rownames(retval) <- names(r.effects)
## }else{
## if(!is.null(conf.int))
## warning("Confidence interval calculation for mer objects requires simulation -- use sim.mer = TRUE")
## est <- fixef(r)
## se <- sqrt(diag(as.matrix(vcov(r))))
## tval <- est/se
## retval <- cbind(
## "Estimate"= est,
## "Std. Error"= se,
## "t-value"= tval
## )
## }
## if( !showall )
## {
## if( !is.R() && ncol(cmat)==1 )
## {
## retval <- retval[varname,,drop=FALSE]
## rownames(retval) <- rn
## }else{
## rn <- paste(varname,rownames(coeff),sep="")
## ind <- match(rn,rownames(retval))
## retval <- retval[ind,,drop=FALSE]
## }
## }
## return(retval)
## }
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.