qvcalc/0000755000176200001440000000000014745002002011515 5ustar liggesusersqvcalc/tests/0000755000176200001440000000000014744767504012707 5ustar liggesusersqvcalc/tests/testthat/0000755000176200001440000000000014745002002014517 5ustar liggesusersqvcalc/tests/testthat/test-qvcalc_survival.R0000644000176200001440000000235214744767504021055 0ustar liggesusers testthat::test_that("qvcalc.survival works", { testthat::skip_if_not_installed("survival") require(survival) ## Example of a "coxph" model cancer_model <- coxph(Surv(time,status) ~ celltype, data = survival::veteran) celltype_qv <- qvcalc(cancer_model, "celltype") testthat::expect_named( celltype_qv, c("covmat", "qvframe", "dispersion", "relerrs", "factorname", "coef.indices", "modelcall") ) testthat::expect_equal( celltype_qv$qvframe$quasiSE, c(0.202377154559161, 0.150182798946618, 0.204942728570679, 0.199186083176635) ) }) ## Example of a "survreg" model testthat::test_that("qvcalc.survreg works", { testthat::skip_if_not_installed("survival") require(survival) cancer_model <- survreg(Surv(time,status) ~ celltype, data = survival::veteran, dist = "weibull") celltype_qv <- qvcalc(cancer_model, "celltype") testthat::expect_named( celltype_qv, c("covmat", "qvframe", "dispersion", "relerrs", "factorname", "coef.indices", "modelcall") ) testthat::expect_equal( celltype_qv$qvframe$quasiSE, c(0.185265780005981, 0.153700051379706, 0.202218015403209, 0.202439832203988) ) }) qvcalc/tests/testthat/test-itempar.R0000644000176200001440000000223314744767504017310 0ustar liggesuserstestthat::test_that("qvcalc.itempar works for raschmodel", { testthat::skip_if_not_installed("psychotools") require(psychotools) data("VerbalAggression", package = "psychotools") raschmod <- raschmodel(VerbalAggression$resp2) ip1 <- itempar(raschmod) qv1 <- qvcalc(ip1) testthat::expect_named( qv1, c("covmat", "qvframe", "dispersion", "relerrs", "factorname", "coef.indices", "modelcall") ) testthat::expect_equal( qv1$qvframe$quasiSE, c(0.142789774392438, 0.142789905559146, 0.132814807950912, 0.131468016260111, 0.130384669951173, 0.1376080489105, 0.157119357966682, 0.136496922430792, 0.134312458828237, 0.13043098568674, 0.130367526373492, 0.15154135165623, 0.132499539340459, 0.130872793612835, 0.134902557606665, 0.152212972001133, 0.152900324421324, 0.229780852197773, 0.139997658112739, 0.134312458828237, 0.131624427111856, 0.131867589722712, 0.140748230935064, 0.170242788920416 ) ) ip2 <- itempar(raschmod, alias = FALSE) testthat::expect_error({ qvcalc(ip2) }) ip2 <- itempar(raschmod, vcov = FALSE) testthat::expect_error({ qvcalc(ip2) }, regexp = "vcov") }) qvcalc/tests/testthat/test-qvcalc_glm.R0000644000176200001440000000340314744767504017757 0ustar liggesuserstestthat::test_that("qvcalc.default works for glm", { ## Overdispersed Poisson loglinear model for ship damage data ## from McCullagh and Nelder (1989), Sec 6.3.2 testthat::skip_if_not_installed("MASS") require(MASS) data(ships) ships$year <- as.factor(ships$year) ships$period <- as.factor(ships$period) shipmodel <- glm(formula = incidents ~ type + year + period, family = quasipoisson, data = ships, subset = (service > 0), offset = log(service)) shiptype.qv <- qvcalc(shipmodel, "type") testthat::expect_named( shiptype.qv, c("covmat", "qvframe", "dispersion", "relerrs", "factorname", "coef.indices", "modelcall") ) testthat::expect_equal( shiptype.qv$qvframe$quasiSE, c(0.200965853501369, 0.112705161723464, 0.375250492322657, 0.323893536427565, 0.232171862907782) ) testthat::expect_error({ qvcalc(shipmodel, "period") }, regexp = "factors with 3 or more levels") testthat::expect_error({ qvcalc(shipmodel) }, regexp = "both NULL") summary(shiptype.qv) print(shiptype.qv) testthat::expect_silent({ plot(shiptype.qv) }) # no intercept model shipmodel2 <- glm(formula = incidents ~ type + year + period - 1, family = quasipoisson, data = ships, subset = (service > 0), offset = log(service)) shiptype.qv2 <- qvcalc(shipmodel2, "type") testthat::expect_equal( shiptype.qv$qvframe$quasiSE, shiptype.qv2$qvframe$quasiSE ) # no intercept model - using coef indices shiptype.qv2 <- qvcalc(shipmodel2, coef.indices = 1:5) testthat::expect_equal( shiptype.qv$qvframe$quasiSE, shiptype.qv2$qvframe$quasiSE ) }) qvcalc/tests/testthat.R0000644000176200001440000000061014744767504014667 0ustar liggesusers# This file is part of the standard setup for testthat. # It is recommended that you do not modify it. # # Where should you do additional test configuration? # Learn more about the roles of various files in: # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview # * https://testthat.r-lib.org/articles/special-files.html library(testthat) library(qvcalc) test_check("qvcalc") qvcalc/MD50000644000176200001440000000165514745002002012034 0ustar liggesusers245a4a9930e8360a6528e5c45eb651e0 *DESCRIPTION 133a40208f0a94f28baa490975a8c428 *NAMESPACE f9dcdd7070eac7b4ef20d5a98565747b *NEWS.md 50183c205d017c4c74ba9d122d539500 *R/qvcalc.R 782544b700a959f893fca74796cedf32 *R/qvcalc.coxph.R 4cc9ab1f4d58a069c9bb96b3113857ed *R/qvcalc.itempar.R 49a457b43f7632075bd871196e24b52e *R/qvcalc.lm.R 9eabedd92d1c0971f97993ca8b0afa4e *R/qvcalc.survreg.R d302813bac6860fc53a429d3a3165351 *R/worstErrors.R 76161b65639451c966be75488458b3c3 *build/partial.rdb 4bcbe035b557f7deb5e9b587201022d2 *man/indentPrint.Rd 7941914d2532cea27a912c9a70884e1f *man/plot.qv.Rd d73e388a55378f5fbcae06fbc6df64ec *man/qvcalc.Rd 2f8baa7f062c4c848100ee8bfbef5328 *man/worstErrors.Rd 3014366c2801ba2760651aa721d3cacf *tests/testthat.R d28f6617aca6aa8365a9647443187808 *tests/testthat/test-itempar.R 3e9c3d63b5e14a4057ea448ffc26161b *tests/testthat/test-qvcalc_glm.R 83c8c8baf64f8334ee79c831ca72b920 *tests/testthat/test-qvcalc_survival.R qvcalc/R/0000755000176200001440000000000014744767504011746 5ustar liggesusersqvcalc/R/qvcalc.lm.R0000644000176200001440000000502314744767504013751 0ustar liggesusers#' @export #' #' @rdname qvcalc #' qvcalc.lm <- function(object, factorname = NULL, coef.indices = NULL, dispersion = NULL, ...) { coef.indices.saved <- coef.indices if (is.null(factorname) && is.null(coef.indices)) { stop("arguments 'factorname' and 'coef.indices' are both NULL") } if (is.null(coef.indices)) { ## try to use factorname term.index <- which(attr(terms(object),"term.labels") == factorname) modelmat <- model.matrix(object) has.coef <- colnames(modelmat) %in% names(coef(object)) coef.indices <- which(attr(modelmat, "assign")[has.coef] == term.index) if (length(object$xlevels[[factorname]]) == length(coef.indices)){ ## factor has no constraint applied, eg if no intercept in model contmat <- diag(length(coef.indices))} else contmat <- eval(call(object$contrasts[[factorname]], object$xlevels[[factorname]])) estimates <- contmat %*% coef(object)[coef.indices] covmat <- vcov(object, dispersion = dispersion) covmat <- covmat[coef.indices, coef.indices, drop = FALSE] covmat <- contmat %*% covmat %*% t(contmat) } else { k <- length(coef.indices) refPos <- numeric(0) if (0 %in% coef.indices) { ## there's a reference level to include refPos <- which(coef.indices == 0) coef.indices <- coef.indices[-refPos] } covmat <- vcov(object, dispersion = dispersion) covmat <- covmat[coef.indices, coef.indices, drop = FALSE] estimates <- coef(object)[coef.indices] if (length(refPos) == 1) { if (length(estimates) != k) estimates <- c(0, estimates) covmat <- cbind(0, rbind(0, covmat)) names(estimates)[1] <- rownames(covmat)[1] <- colnames(covmat)[1] <- "(reference)" if (refPos != 1) { if (refPos == k){ perm <- c(2:k, 1) } else { perm <- c(2:refPos, 1, (refPos + 1):k) } estimates <- estimates[perm] covmat <- covmat[perm, perm, drop = FALSE] } } } return(qvcalc.default(covmat, factorname = factorname, coef.indices = coef.indices.saved, labels = NULL, dispersion = dispersion, estimates = estimates, modelcall = object$call, ...) ) } qvcalc/R/qvcalc.coxph.R0000644000176200001440000000027514744767504014466 0ustar liggesusers#' @export #' @rdname qvcalc qvcalc.coxph <- function(object, factorname = NULL, coef.indices = NULL, ...) { qvcalc.lm(object, factorname, coef.indices, ...) } qvcalc/R/worstErrors.R0000644000176200001440000000452014744767504014445 0ustar liggesusers#' Accuracy of a Quasi-variance Approximation #' #' Computes the worst relative error, among all contrasts, for the standard #' error as derived from a set of quasi variances. For details of the method #' see Menezes (1999) or Firth and Menezes (2004). #' #' @param qv.object An object of class \code{qv} #' #' @return A numeric vector of length 2, the worst negative relative error and #' the worst positive relative error. #' #' @author David Firth, \email{d.firth@@warwick.ac.uk} #' #' @seealso \code{\link{qvcalc}} #' #' @references #' #' Firth, D. and Mezezes, R. X. de (2004) Quasi-variances. #' \emph{Biometrika} \bold{91}, 69--80. #' \doi{10.1093/biomet/91.1.65} #' #' McCullagh, P. and Nelder, J. A. (1989) \emph{Generalized Linear Models}. #' London: Chapman and Hall. #' #' Menezes, R. X. (1999) More useful standard errors for group and factor #' effects in generalized linear models. \emph{D.Phil. Thesis}, Department of #' Statistics, University of Oxford. #' #' @keywords regression models #' #' @examples #' #' ## Overdispersed Poisson loglinear model for ship damage data #' ## from McCullagh and Nelder (1989), Sec 6.3.2 #' library(MASS) #' data(ships) #' ships$year <- as.factor(ships$year) #' ships$period <- as.factor(ships$period) #' shipmodel <- glm(formula = incidents ~ type + year + period, #' family = quasipoisson, #' data = ships, subset = (service > 0), offset = log(service)) #' shiptype.qvs <- qvcalc(shipmodel, "type") #' summary(shiptype.qvs, digits = 4) #' worstErrors(shiptype.qvs) #' #' @export #' worstErrors <- function(qv.object) { reducedForm <- function(covmat, qvmat){ nlevels <- dim(covmat)[1] firstRow <- covmat[1, ] ones <- rep(1, nlevels) J <- outer(ones, ones) notzero <- 2:nlevels r.covmat <- covmat + (firstRow[1]*J) - outer(firstRow, ones) - outer(ones, firstRow) r.covmat <- r.covmat[notzero, notzero] qv1 <- qvmat[1, 1] r.qvmat <- (qvmat + qv1*J)[notzero, notzero] list(r.covmat, r.qvmat)} covmat <- qv.object$covmat qvmat <- diag(qv.object$qvframe$quasiVar) r.form <- reducedForm(covmat, qvmat) r.covmat <- r.form[[1]] r.qvmat <- r.form[[2]] inverse.sqrt <- solve(chol(r.covmat)) evalues <- eigen(t(inverse.sqrt) %*% r.qvmat %*% inverse.sqrt, symmetric=TRUE)$values sqrt(c(min(evalues), max(evalues))) - 1 } qvcalc/R/qvcalc.survreg.R0000644000176200001440000000030514744767504015034 0ustar liggesusers#' @export #' #' @rdname qvcalc #' qvcalc.survreg <- function(object, factorname = NULL, coef.indices = NULL, ...) { qvcalc.lm(object, factorname, coef.indices, ...) } qvcalc/R/qvcalc.R0000644000176200001440000004643714744767504013360 0ustar liggesusers## The qvcalc generic and default method. And methods for print, summary and plot, ## for a resulting "qv" object. #' Quasi Variances for Model Coefficients #' #' Computes a set of quasi variances (and corresponding quasi standard errors) #' for estimated model coefficients relating to the levels of a categorical #' (i.e., factor) explanatory variable. For details of the method see Firth #' (2000), Firth (2003) or Firth and de Menezes (2004). Quasi variances #' generalize and improve the accuracy of \dQuote{floating absolute risk} #' (Easton et al., 1991). This device for economical model summary was first #' suggested by Ridout (1989). #' #' #' The \code{qvcalc.default} method is the computational backend for all other, #' class-specific methods. #' #' In \code{qvcalc.default}, none of the arguments other than \code{object} is #' used in computing the result. The remaining arguments are simply passed #' through to the result object as components to help with record-keeping etc. #' #' In \code{qvcalc.lm}, at least one of \code{factorname} or #' \code{coef.indices} must be non-\code{NULL}. The value of #' \code{coef.indices}, if non-\code{NULL}, determines which rows and columns #' of the model's variance-covariance matrix to use. If \code{coef.indices} #' contains a zero, then an extra row and column are included at the indicated #' position, to represent the zero variances and covariances associated with a #' reference level. If \code{coef.indices} is \code{NULL}, then #' \code{factorname} should be the name of a factor effect in the model, and is #' used in order to extract the necessary variance-covariance estimates. #' #' For \code{qvcalc.itempar}, the \code{"itempar"} object must have the full #' variance-covariance matrix in its \code{"vcov"} attribute, and must have its #' \code{"alias"} attribute be \code{TRUE}. These attributes result from use #' of the default arguments \code{vcov = TRUE, alias = TRUE} when the #' \code{\link[psychotools]{itempar}} function is called. #' #' Ordinarily the quasi variances are positive and so their square roots (the #' quasi standard errors) exist and can be used in plots, etc. #' #' Occasionally one (and only one) of the quasi variances is negative, and so #' the corresponding quasi standard error does not exist (it appears as #' \code{NaN}). This is fairly rare in applications, and when it occurs it is #' because the factor of interest is strongly correlated with one or more other #' predictors in the model. It is not an indication that quasi variances are #' inaccurate. An example is shown below using data from the \code{car} #' package: the quasi variance approximation is exact (since \code{type} has #' only 3 levels), and there is a negative quasi variance. The quasi variances #' remain perfectly valid (they can be used to obtain inference on any #' contrast), but it makes no sense to plot `comparison intervals' in the usual #' way since one of the quasi standard errors is not a real number. #' #' @aliases qvcalc qvcalc.default qvcalc.lm qvcalc.itempar qvcalc.coxph #' qvcalc.survreg summary.qv print.qv #' @param object For \code{qvcalc.default}, this is the covariance (sub)matrix #' for the parameters of interest (including any that may have been constrained #' to zero). For the generic \code{qvcalc}, the \code{object} can be any #' object for which the relevant S3 method has been defined. These currently #' include many types of regression model (via \code{qvcalc.lm}), including #' objects of classes \code{\link[survival]{coxph}} and #' \code{\link[survival]{survreg}}; and also objects of class #' \code{\link[psychotools]{itempar}}. #' @param factorname Either \code{NULL}, or a character vector of length 1 #' @param coef.indices Either \code{NULL}, or a numeric vector of length at #' least 3 #' @param labels An optional vector of row names for the \code{qvframe} #' component of the result (redundant if \code{object} is a model) #' @param dispersion an optional scalar multiplier for the covariance matrix, #' to cope with overdispersion for example #' @param estimates an optional vector of estimated coefficients (redundant if #' \code{object} is a model, for example) #' @param modelcall optional, the call expression for the model of interest #' (redundant if \code{object} is a model with its own \code{call} component) #' @param ... other arguments to pass to \code{qv.default} #' @return A list of class \code{qv}, with components \item{covmat}{the full #' variance-covariance matrix for the estimated coefficients corresponding to #' the factor of interest} \item{qvframe}{a data frame with variables #' \code{estimate}, \code{SE}, \code{quasiSE} and \code{quasiVar}, the last two #' being a quasi standard error and quasi-variance for each level of the factor #' of interest} \item{relerrs}{relative errors for approximating the standard #' errors of all simple contrasts} \item{factorname}{the factor name if given} #' \item{coef.indices}{the coefficient indices if given} \item{modelcall}{if #' \code{object} is a model, \code{object$call}; otherwise \code{NULL}} #' @author David Firth, \email{d.firth@@warwick.ac.uk} #' @seealso \code{\link{worstErrors}}, \code{\link{plot.qv}}. #' @references Easton, D. F, Peto, J. and Babiker, A. G. A. G. (1991) Floating #' absolute risk: an alternative to relative risk in survival and case-control #' analysis avoiding an arbitrary reference group. \emph{Statistics in #' Medicine} \bold{10}, 1025--1035. \doi{10.1002/sim.4780100703} #' #' Firth, D. (2000) Quasi-variances in Xlisp-Stat and on the web. #' \emph{Journal of Statistical Software} \bold{5.4}, 1--13. #' \doi{10.18637/jss.v005.i04} #' #' Firth, D. (2003) Overcoming the reference category problem in the #' presentation of statistical models. \emph{Sociological Methodology} #' \bold{33}, 1--18. \doi{10.1111/j.0081-1750.2003.t01-1-00125.x} #' #' Firth, D. and de Mezezes, R. X. (2004) Quasi-variances. \emph{Biometrika} #' \bold{91}, 65--80. \doi{10.1093/biomet/91.1.65} #' #' McCullagh, P. and Nelder, J. A. (1989) \emph{Generalized Linear Models}. #' London: Chapman and Hall. #' #' Menezes, R. X. de (1999) More useful standard errors for group and factor #' effects in generalized linear models. \emph{D.Phil. Thesis}, Department of #' Statistics, University of Oxford. #' #' Ridout, M.S. (1989). Summarizing the results of fitting generalized linear #' models to data from designed experiments. In: \emph{Statistical Modelling: #' Proceedings of GLIM89 and the 4th International Workshop on Statistical #' Modelling held in Trento, Italy, July 17--21, 1989} (A. Decarli et al., #' eds.), pp 262--269. New York: Springer. #' @keywords models regression #' @examples #' #' ## Overdispersed Poisson loglinear model for ship damage data #' ## from McCullagh and Nelder (1989), Sec 6.3.2 #' if (require(MASS)) { #' data(ships) #' ships$year <- as.factor(ships$year) #' ships$period <- as.factor(ships$period) #' shipmodel <- glm(formula = incidents ~ type + year + period, #' family = quasipoisson, #' data = ships, #' subset = (service > 0), #' offset = log(service)) #' shiptype.qv <- qvcalc(shipmodel, "type") #' #' ## We can plot "comparison intervals" as follows: #' ## plot(shiptype.qv, xlab = "ship type") #' #' ## An equivalent result by using the coef.indices argument instead: #' ## shiptype.qv2 <- qvcalc(shipmodel, coef.indices = c(0, 2:5)) #' #' summary(shiptype.qv, digits = 4) #' } #' #' ## Example of a "coxph" model #' if(require(survival)) { #' data("veteran", package = "survival") #' cancer_model <- coxph(Surv(time,status) ~ celltype, data = veteran) #' celltype_qv <- qvcalc(cancer_model, "celltype") #' summary(celltype_qv) #' } #' #' ## Example of a "survreg" model #' if(require(survival)) { #' data("veteran", package = "survival") #' cancer_model2 <- survreg(Surv(time,status) ~ celltype, data = veteran, #' dist = "weibull") #' celltype_qv2 <- qvcalc(cancer_model2, "celltype") #' summary(celltype_qv2) #' } #' #' ## Based on an example from ?itempar #' if(require(psychotools)) { #' data("VerbalAggression", package = "psychotools") #' raschmod <- raschmodel(VerbalAggression$resp2) #' ip1 <- itempar(raschmod) #' qv1 <- qvcalc(ip1) #' summary(qv1) } #' #' ## Example of a negative quasi variance #' ## Requires the "car" package #' \dontrun{ #' library(car) #' data(Prestige) #' attach(Prestige) #' mymodel <- lm(prestige ~ type + education) #' library(qvcalc) #' type.qvs <- qvcalc(mymodel, "type") #' ## Warning message: #' ## In sqrt(qv) : NaNs produced #' summary(type.qvs) #' ## Model call: lm(formula = prestige ~ type + education) #' ## Factor name: type #' ## estimate SE quasiSE quasiVar #' ## bc 0.000000 0.000000 2.874361 8.261952 #' ## prof 6.142444 4.258961 3.142737 9.876793 #' ## wc -5.458495 2.690667 NaN -1.022262 #' ## Worst relative errors in SEs of simple contrasts (%): 0 0 #' ## Worst relative errors over *all* contrasts (%): 0 0 #' plot(type.qvs) #' ## Error in plot.qv(type.qvs) : No comparison intervals available, #' ## since one of the quasi variances is negative. See ?qvcalc for more. #' } #' #' @export qvcalc <- function (object, ...) UseMethod("qvcalc") #' @export #' @rdname qvcalc qvcalc.default <- function(object, factorname = NULL, coef.indices = NULL, labels = NULL, dispersion = NULL, estimates = NULL, modelcall = NULL, ...) { covmat <- object if (!is.null(labels)) rownames(covmat) <- colnames(covmat) <- labels n <- dim(covmat)[1] if (n <= 2) stop( "qvcalc works only for factors with 3 or more levels") simple.contrasts <- function(n, levelnames = 1:n){ result <- list() for (i in 1:(n-1)){ for (j in (i+1):n){ result[[paste(levelnames[i], levelnames[j], sep = ",")]] <- c(i, j)}} result } qvdesign <- function(n){ nrows <- choose(n, 2) m <- matrix(0, nrows, n) indices <- simple.contrasts(n) for (i in 1:nrows){ m[i, indices[[i]][1]] <- 1 m[i, indices[[i]][2]] <- 1} m } level <- qvdesign(n) contrast.variance <- function(contrast, covmat){ if (!(is.matrix(covmat) && (dim(covmat)[1] == dim(covmat)[2]))) stop("covmat must be a square matrix") n <- dim(covmat)[1] if (length(contrast) == n && sum(contrast) == 0) ## arbitrary contrast vector return(as.vector(contrast %*% covmat %*% contrast)) if (length(contrast) == 2 && all(contrast %in% 1:n)){ ## simple contrast specified as an index pair i <- contrast[1] j <- contrast[2] return(covmat[i,i] + covmat[j,j] - 2*covmat[i,j])} else stop("invalid contrast") } simple.contrast.variances <- function(n, covmat){ if (!is.null(rownames(covmat))) levelnames <- rownames(covmat) else levelnames <- 1:n sapply(simple.contrasts(n, levelnames), function(contrast){contrast.variance(contrast, covmat)}) } response <- simple.contrast.variances(n, covmat) if (any(response <= 0)) { stop("not all contrasts have positive variance") } else response <- log(response) expLinear <- structure(list( family = "expLinear", link = "exp", linkfun = function(mu) exp(mu), linkinv = function(eta) log(eta), variance = function(mu) rep(1, length(mu)), dev.resids = function(y, mu, wt) wt * ((y - mu)^2), aic = function(y, n, mu, wt, dev) sum(wt) * (log(dev/sum(wt) * 2 * pi) + 1) + 2, mu.eta = function (eta) 1/eta, initialize = expression({ n <- rep(1, nobs) mustart <- y}), validmu = function(mu) TRUE), class = "family") model <- glm(response ~ 0 + level, family = expLinear) qv <- coef(model) NAs <- rep(NA, length(qv)) if (!is.null(rownames(covmat))) names(qv) <- rownames(covmat) frame <- data.frame(estimate = NAs, SE = sqrt(diag(covmat)), quasiSE = sqrt(qv), quasiVar = qv, row.names = names(qv)) if (!is.null(estimates)) frame$estimate <- estimates relerrs <- sqrt(exp(- residuals(model))) - 1 ## The above formula was corrected in v0.8-9; it ## previously said 1 - sqrt(exp(residuals(model)), which is ## not what should be expected for "relative error" here. ## This corrected version agrees with the Biometrika paper. ## Thanks to Shaun Killingbeck for spotting this error in the ## previous version. names(relerrs) <- names(response) return(structure(list(covmat = covmat, qvframe = frame, dispersion = dispersion, relerrs = relerrs, factorname = factorname, coef.indices = coef.indices, modelcall = modelcall), class="qv")) } #' Print with Line Indentation #' #' Same as \code{\link{print}}, but adds a specified amount of white space at #' the start of each printed line #' #' #' @param object any printable object #' @param indent a non-negative integer, the number of spaces to insert #' @param \dots other arguments to pass to \code{\link{print}} #' @return \code{object} is returned invisibly #' @author David Firth, \email{d.firth@@warwick.ac.uk} #' @keywords IO #' @examples #' #' indentPrint("this indented by 10 spaces", indent=10) #' #' @export indentPrint <- function(object, indent = 4, ...){ zz <- "" tc <- textConnection("zz", "w", local = TRUE) sink(tc) try(print(object, ...)) sink() close(tc) indent <- paste(rep(" ", indent), sep = "", collapse = "") cat(paste(indent, zz, sep = ""), sep = "\n")} #' @export print.qv <- function(x, ...){ print(x$qvframe) } #' @export summary.qv <- function(object, ...) { if (!is.null(object$modelcall)) cat("Model call: ", deparse(object$modelcall), "\n") if (!is.null(object$dispersion)) cat("Dispersion: ", object$dispersion, "\n") if (!is.null(object$factorname)) cat("Factor name: ",object$factorname,"\n") indentPrint(object$qvframe,...) if (!is.null(object$relerrs)){ minErrSimple <- round(100*min(object$relerrs), 1) maxErrSimple <- round(100*max(object$relerrs), 1) errors<-worstErrors(object) minErrOverall<-round(100*errors[1], 1) maxErrOverall<-round(100*errors[2], 1) cat("Worst relative errors in SEs of simple contrasts (%): ", minErrSimple, maxErrSimple, "\n") cat("Worst relative errors over *all* contrasts (%): ", minErrOverall, maxErrOverall, "\n") } } #' Plot method for objects of class qv #' #' Provides visualization of estimated contrasts using intervals based on quasi #' standard errors. #' #' If \code{levelNames} is unspecified, the row names of \code{x$qvframe} will #' be used. #' #' @param x an object of class \code{"qv"}, typically the result of calling #' \code{\link{qvcalc}} #' @param intervalWidth the half-width, in quasi standard errors, of the #' plotted intervals #' @param ylab as for \code{\link{plot.default}} #' @param xlab as for \code{\link{plot.default}} #' @param ylim as for \code{\link{plot.default}} #' @param main as for \code{\link{plot.default}} #' @param levelNames labels to be used on the x axis for the levels of the #' factor whose effect is plotted #' @param \dots other arguments understood by \code{plot} #' @return \code{invisible(x)} #' @author David Firth, \email{d.firth@@warwick.ac.uk} #' @seealso \code{\link{qvcalc}} #' @references #' #' Easton, D. F, Peto, J. and Babiker, A. G. A. G. (1991) Floating #' absolute risk: an alternative to relative risk in survival and case-control #' analysis avoiding an arbitrary reference group. \emph{Statistics in #' Medicine} \bold{10}, 1025--1035. \doi{10.1002/sim.4780100703} #' #' Firth, D. (2000) Quasi-variances in Xlisp-Stat and on the web. #' \emph{Journal of Statistical Software} \bold{5.4}, 1--13. #' \doi{10.18637/jss.v005.i04} #' #' Firth, D. (2003) Overcoming the reference category problem in the #' presentation of statistical models. \emph{Sociological Methodology} #' \bold{33}, 1--18. \doi{10.1111/j.0081-1750.2003.t01-1-00125.x} #' #' Firth, D. and Mezezes, R. X. de (2004) Quasi-variances. \emph{Biometrika} #' \bold{91}, 65--80. \doi{10.1093/biomet/91.1.65} #' #' McCullagh, P. and Nelder, J. A. (1989) \emph{Generalized Linear Models}. #' London: Chapman and Hall. #' #' Menezes, R. X. (1999) More useful standard errors for group and factor #' effects in generalized linear models. \emph{D.Phil. Thesis}, Department of #' Statistics, University of Oxford. #' #' @keywords models hplot #' @examples #' #' ## Overdispersed Poisson loglinear model for ship damage data #' ## from McCullagh and Nelder (1989), Sec 6.3.2 #' library(MASS) #' data(ships) #' ships$year <- as.factor(ships$year) #' ships$period <- as.factor(ships$period) #' shipmodel <- glm(formula = incidents ~ type + year + period, #' family = quasipoisson, #' data = ships, subset = (service > 0), offset = log(service)) #' qvs <- qvcalc(shipmodel, "type") #' summary(qvs, digits = 4) #' plot(qvs, col = c(rep("red", 4), "blue")) #' ## if we want to plot in decreasing order (of estimates): #' est <- qvs$qvframe$estimate #' qvs2 <- qvs #' qvs2$qvframe <- qvs$qvframe[order(est, decreasing = TRUE), , drop = FALSE] #' plot(qvs2) #' #' @export #' plot.qv <- function(x, intervalWidth = 2, ylab = "estimate", xlab = "", ylim = NULL, main = "Intervals based on quasi standard errors", levelNames = NULL, ...) { frame <- x$qvframe if (!is.null(levelNames)) { if (nrow(frame) != length(levelNames)) stop( "levelNames is not a vector of the right length" ) row.names(frame) <- levelNames } if (is.null(frame$quasiSE)) stop("Cannot plot, because there are no quasi standard errors") if (is.na(frame$estimate[1])) stop("No parameter estimates to plot") if (any(is.nan(frame$quasiSE))) stop(paste("No comparison intervals available,\n", "since one of the quasi variances is negative.", " See ?qvcalc for more.", sep = "")) faclevels <- factor(row.names(frame), levels = row.names(frame)) xvalues <- seq(along = faclevels) est <- frame$estimate se <- frame$quasiSE tops <- est + (intervalWidth * se) tails <- est - (intervalWidth * se) range <- max(tops) - min(tails) if (is.null(ylim)) ylim <- c(min(tails) - range/10, max(tops) + range/10) plot(faclevels, frame$estimate, border = "transparent", ylim = ylim, xlab = xlab, ylab = ylab, main = main, ...) points(frame$estimate, ...) segments(xvalues, tails, xvalues, tops, ...) invisible(x) } qvcalc/R/qvcalc.itempar.R0000644000176200001440000000053614744767504015006 0ustar liggesusers#' @export #' @rdname qvcalc qvcalc.itempar <- function(object, ...){ alias = attr(object, "alias") if (!isTRUE(alias)) stop( "the itempar object was not built with 'alias = TRUE'") vc <- vcov(object) if (any(is.na(vc))) stop("the itempar object was not built with 'vcov = TRUE'") qvcalc.default(vc, estimates = object) } qvcalc/NAMESPACE0000644000176200001440000000070714744767504012770 0ustar liggesusersimportFrom("graphics", "plot", "points", "segments") importFrom("stats", "coef", "glm", "model.matrix", "residuals", "terms", "vcov") export(qvcalc, worstErrors, indentPrint, qvcalc.default, qvcalc.lm, qvcalc.coxph, qvcalc.itempar, qvcalc.survreg) S3method(print, qv) S3method(summary, qv) S3method(plot, qv) S3method(qvcalc, itempar) S3method(qvcalc, lm) S3method(qvcalc, coxph) S3method(qvcalc, survreg) S3method(qvcalc, default) qvcalc/NEWS.md0000644000176200001440000000315214744767504012644 0ustar liggesusers# qvcalc 1.0.4 * Minor updates to documentation, and added some tests (thanks to John Muschelli for this). Added ORCID details in the DESCRIPTION file. # qvcalc 1.0.3 * Replaced URLs by DOIs, in function documentation references. # qvcalc 1.0.2 * Added an explicit method for "survreg" objects. # qvcalc 1.0.1 * Added an explicit method for "coxph" objects. * Removed the `Suggests: pkgdown` dependence, because we no longer use Travis CI to deploy the documentation site. # qvcalc 1.0.0 * Fixed a minor bug in `plot.qv()` * Added an example to the help page for `plot.qv`, to show how to re-order the points/lines in a call to `plot.qv()` # qvcalc 0.9-1 * Reorganised `qvcalc` as an S3 generic function, to allow others to provide class-specific methods. * The package includes method `qvcalc.lm` for linear and generalized linear models. The back-end computation is now done in `qvcalc.default`. * The method for `BTabilities` objects is now moved to the `BradleyTerry2` package (version 1.0-8). Thanks go to Heather Turner for that. # qvcalc 0.9-0 * Minor tweaks to fix the dependencies `NOTE` on CRAN checks # qvcalc 0.8-9 * Corrects an error in the calculation of the relative errors for simple contrasts. The formula used for this now agrees with the definition of relative error that was given in the Biometrika paper. Many thanks to Shaun Killingbeck for spotting the error in version 0.8-8. Also made some small improvements to examples, and cosmetic changes to avoid a `NOTE` in the latest CRAN checks. ----- *This history starts with version 0.8-9 (3 February 2015). Earlier versions are not listed here.* qvcalc/build/0000755000176200001440000000000014744767534012647 5ustar liggesusersqvcalc/build/partial.rdb0000644000176200001440000000007514744767534014776 0ustar liggesusers‹‹àb```b`aab`b1…ÀÈg``d`aàÒ¬y‰¹©Å@†D’áÝ?M7qvcalc/man/0000755000176200001440000000000014744767504012320 5ustar liggesusersqvcalc/man/indentPrint.Rd0000644000176200001440000000126714744767504015113 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/qvcalc.R \name{indentPrint} \alias{indentPrint} \title{Print with Line Indentation} \usage{ indentPrint(object, indent = 4, ...) } \arguments{ \item{object}{any printable object} \item{indent}{a non-negative integer, the number of spaces to insert} \item{\dots}{other arguments to pass to \code{\link{print}}} } \value{ \code{object} is returned invisibly } \description{ Same as \code{\link{print}}, but adds a specified amount of white space at the start of each printed line } \examples{ indentPrint("this indented by 10 spaces", indent=10) } \author{ David Firth, \email{d.firth@warwick.ac.uk} } \keyword{IO} qvcalc/man/plot.qv.Rd0000644000176200001440000000562414744767504014221 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/qvcalc.R \name{plot.qv} \alias{plot.qv} \title{Plot method for objects of class qv} \usage{ \method{plot}{qv}( x, intervalWidth = 2, ylab = "estimate", xlab = "", ylim = NULL, main = "Intervals based on quasi standard errors", levelNames = NULL, ... ) } \arguments{ \item{x}{an object of class \code{"qv"}, typically the result of calling \code{\link{qvcalc}}} \item{intervalWidth}{the half-width, in quasi standard errors, of the plotted intervals} \item{ylab}{as for \code{\link{plot.default}}} \item{xlab}{as for \code{\link{plot.default}}} \item{ylim}{as for \code{\link{plot.default}}} \item{main}{as for \code{\link{plot.default}}} \item{levelNames}{labels to be used on the x axis for the levels of the factor whose effect is plotted} \item{\dots}{other arguments understood by \code{plot}} } \value{ \code{invisible(x)} } \description{ Provides visualization of estimated contrasts using intervals based on quasi standard errors. } \details{ If \code{levelNames} is unspecified, the row names of \code{x$qvframe} will be used. } \examples{ ## Overdispersed Poisson loglinear model for ship damage data ## from McCullagh and Nelder (1989), Sec 6.3.2 library(MASS) data(ships) ships$year <- as.factor(ships$year) ships$period <- as.factor(ships$period) shipmodel <- glm(formula = incidents ~ type + year + period, family = quasipoisson, data = ships, subset = (service > 0), offset = log(service)) qvs <- qvcalc(shipmodel, "type") summary(qvs, digits = 4) plot(qvs, col = c(rep("red", 4), "blue")) ## if we want to plot in decreasing order (of estimates): est <- qvs$qvframe$estimate qvs2 <- qvs qvs2$qvframe <- qvs$qvframe[order(est, decreasing = TRUE), , drop = FALSE] plot(qvs2) } \references{ Easton, D. F, Peto, J. and Babiker, A. G. A. G. (1991) Floating absolute risk: an alternative to relative risk in survival and case-control analysis avoiding an arbitrary reference group. \emph{Statistics in Medicine} \bold{10}, 1025--1035. \doi{10.1002/sim.4780100703} Firth, D. (2000) Quasi-variances in Xlisp-Stat and on the web. \emph{Journal of Statistical Software} \bold{5.4}, 1--13. \doi{10.18637/jss.v005.i04} Firth, D. (2003) Overcoming the reference category problem in the presentation of statistical models. \emph{Sociological Methodology} \bold{33}, 1--18. \doi{10.1111/j.0081-1750.2003.t01-1-00125.x} Firth, D. and Mezezes, R. X. de (2004) Quasi-variances. \emph{Biometrika} \bold{91}, 65--80. \doi{10.1093/biomet/91.1.65} McCullagh, P. and Nelder, J. A. (1989) \emph{Generalized Linear Models}. London: Chapman and Hall. Menezes, R. X. (1999) More useful standard errors for group and factor effects in generalized linear models. \emph{D.Phil. Thesis}, Department of Statistics, University of Oxford. } \seealso{ \code{\link{qvcalc}} } \author{ David Firth, \email{d.firth@warwick.ac.uk} } \keyword{hplot} \keyword{models} qvcalc/man/qvcalc.Rd0000644000176200001440000002261114744767504014062 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/qvcalc.R, R/qvcalc.coxph.R, R/qvcalc.itempar.R, % R/qvcalc.lm.R, R/qvcalc.survreg.R \name{qvcalc} \alias{qvcalc} \alias{qvcalc.default} \alias{qvcalc.lm} \alias{qvcalc.itempar} \alias{qvcalc.coxph} \alias{qvcalc.survreg} \alias{summary.qv} \alias{print.qv} \title{Quasi Variances for Model Coefficients} \usage{ qvcalc(object, ...) \method{qvcalc}{default}( object, factorname = NULL, coef.indices = NULL, labels = NULL, dispersion = NULL, estimates = NULL, modelcall = NULL, ... ) \method{qvcalc}{coxph}(object, factorname = NULL, coef.indices = NULL, ...) \method{qvcalc}{itempar}(object, ...) \method{qvcalc}{lm}(object, factorname = NULL, coef.indices = NULL, dispersion = NULL, ...) \method{qvcalc}{survreg}(object, factorname = NULL, coef.indices = NULL, ...) } \arguments{ \item{object}{For \code{qvcalc.default}, this is the covariance (sub)matrix for the parameters of interest (including any that may have been constrained to zero). For the generic \code{qvcalc}, the \code{object} can be any object for which the relevant S3 method has been defined. These currently include many types of regression model (via \code{qvcalc.lm}), including objects of classes \code{\link[survival]{coxph}} and \code{\link[survival]{survreg}}; and also objects of class \code{\link[psychotools]{itempar}}.} \item{...}{other arguments to pass to \code{qv.default}} \item{factorname}{Either \code{NULL}, or a character vector of length 1} \item{coef.indices}{Either \code{NULL}, or a numeric vector of length at least 3} \item{labels}{An optional vector of row names for the \code{qvframe} component of the result (redundant if \code{object} is a model)} \item{dispersion}{an optional scalar multiplier for the covariance matrix, to cope with overdispersion for example} \item{estimates}{an optional vector of estimated coefficients (redundant if \code{object} is a model, for example)} \item{modelcall}{optional, the call expression for the model of interest (redundant if \code{object} is a model with its own \code{call} component)} } \value{ A list of class \code{qv}, with components \item{covmat}{the full variance-covariance matrix for the estimated coefficients corresponding to the factor of interest} \item{qvframe}{a data frame with variables \code{estimate}, \code{SE}, \code{quasiSE} and \code{quasiVar}, the last two being a quasi standard error and quasi-variance for each level of the factor of interest} \item{relerrs}{relative errors for approximating the standard errors of all simple contrasts} \item{factorname}{the factor name if given} \item{coef.indices}{the coefficient indices if given} \item{modelcall}{if \code{object} is a model, \code{object$call}; otherwise \code{NULL}} } \description{ Computes a set of quasi variances (and corresponding quasi standard errors) for estimated model coefficients relating to the levels of a categorical (i.e., factor) explanatory variable. For details of the method see Firth (2000), Firth (2003) or Firth and de Menezes (2004). Quasi variances generalize and improve the accuracy of \dQuote{floating absolute risk} (Easton et al., 1991). This device for economical model summary was first suggested by Ridout (1989). } \details{ The \code{qvcalc.default} method is the computational backend for all other, class-specific methods. In \code{qvcalc.default}, none of the arguments other than \code{object} is used in computing the result. The remaining arguments are simply passed through to the result object as components to help with record-keeping etc. In \code{qvcalc.lm}, at least one of \code{factorname} or \code{coef.indices} must be non-\code{NULL}. The value of \code{coef.indices}, if non-\code{NULL}, determines which rows and columns of the model's variance-covariance matrix to use. If \code{coef.indices} contains a zero, then an extra row and column are included at the indicated position, to represent the zero variances and covariances associated with a reference level. If \code{coef.indices} is \code{NULL}, then \code{factorname} should be the name of a factor effect in the model, and is used in order to extract the necessary variance-covariance estimates. For \code{qvcalc.itempar}, the \code{"itempar"} object must have the full variance-covariance matrix in its \code{"vcov"} attribute, and must have its \code{"alias"} attribute be \code{TRUE}. These attributes result from use of the default arguments \code{vcov = TRUE, alias = TRUE} when the \code{\link[psychotools]{itempar}} function is called. Ordinarily the quasi variances are positive and so their square roots (the quasi standard errors) exist and can be used in plots, etc. Occasionally one (and only one) of the quasi variances is negative, and so the corresponding quasi standard error does not exist (it appears as \code{NaN}). This is fairly rare in applications, and when it occurs it is because the factor of interest is strongly correlated with one or more other predictors in the model. It is not an indication that quasi variances are inaccurate. An example is shown below using data from the \code{car} package: the quasi variance approximation is exact (since \code{type} has only 3 levels), and there is a negative quasi variance. The quasi variances remain perfectly valid (they can be used to obtain inference on any contrast), but it makes no sense to plot `comparison intervals' in the usual way since one of the quasi standard errors is not a real number. } \examples{ ## Overdispersed Poisson loglinear model for ship damage data ## from McCullagh and Nelder (1989), Sec 6.3.2 if (require(MASS)) { data(ships) ships$year <- as.factor(ships$year) ships$period <- as.factor(ships$period) shipmodel <- glm(formula = incidents ~ type + year + period, family = quasipoisson, data = ships, subset = (service > 0), offset = log(service)) shiptype.qv <- qvcalc(shipmodel, "type") ## We can plot "comparison intervals" as follows: ## plot(shiptype.qv, xlab = "ship type") ## An equivalent result by using the coef.indices argument instead: ## shiptype.qv2 <- qvcalc(shipmodel, coef.indices = c(0, 2:5)) summary(shiptype.qv, digits = 4) } ## Example of a "coxph" model if(require(survival)) { data("veteran", package = "survival") cancer_model <- coxph(Surv(time,status) ~ celltype, data = veteran) celltype_qv <- qvcalc(cancer_model, "celltype") summary(celltype_qv) } ## Example of a "survreg" model if(require(survival)) { data("veteran", package = "survival") cancer_model2 <- survreg(Surv(time,status) ~ celltype, data = veteran, dist = "weibull") celltype_qv2 <- qvcalc(cancer_model2, "celltype") summary(celltype_qv2) } ## Based on an example from ?itempar if(require(psychotools)) { data("VerbalAggression", package = "psychotools") raschmod <- raschmodel(VerbalAggression$resp2) ip1 <- itempar(raschmod) qv1 <- qvcalc(ip1) summary(qv1) } ## Example of a negative quasi variance ## Requires the "car" package \dontrun{ library(car) data(Prestige) attach(Prestige) mymodel <- lm(prestige ~ type + education) library(qvcalc) type.qvs <- qvcalc(mymodel, "type") ## Warning message: ## In sqrt(qv) : NaNs produced summary(type.qvs) ## Model call: lm(formula = prestige ~ type + education) ## Factor name: type ## estimate SE quasiSE quasiVar ## bc 0.000000 0.000000 2.874361 8.261952 ## prof 6.142444 4.258961 3.142737 9.876793 ## wc -5.458495 2.690667 NaN -1.022262 ## Worst relative errors in SEs of simple contrasts (\%): 0 0 ## Worst relative errors over *all* contrasts (\%): 0 0 plot(type.qvs) ## Error in plot.qv(type.qvs) : No comparison intervals available, ## since one of the quasi variances is negative. See ?qvcalc for more. } } \references{ Easton, D. F, Peto, J. and Babiker, A. G. A. G. (1991) Floating absolute risk: an alternative to relative risk in survival and case-control analysis avoiding an arbitrary reference group. \emph{Statistics in Medicine} \bold{10}, 1025--1035. \doi{10.1002/sim.4780100703} Firth, D. (2000) Quasi-variances in Xlisp-Stat and on the web. \emph{Journal of Statistical Software} \bold{5.4}, 1--13. \doi{10.18637/jss.v005.i04} Firth, D. (2003) Overcoming the reference category problem in the presentation of statistical models. \emph{Sociological Methodology} \bold{33}, 1--18. \doi{10.1111/j.0081-1750.2003.t01-1-00125.x} Firth, D. and de Mezezes, R. X. (2004) Quasi-variances. \emph{Biometrika} \bold{91}, 65--80. \doi{10.1093/biomet/91.1.65} McCullagh, P. and Nelder, J. A. (1989) \emph{Generalized Linear Models}. London: Chapman and Hall. Menezes, R. X. de (1999) More useful standard errors for group and factor effects in generalized linear models. \emph{D.Phil. Thesis}, Department of Statistics, University of Oxford. Ridout, M.S. (1989). Summarizing the results of fitting generalized linear models to data from designed experiments. In: \emph{Statistical Modelling: Proceedings of GLIM89 and the 4th International Workshop on Statistical Modelling held in Trento, Italy, July 17--21, 1989} (A. Decarli et al., eds.), pp 262--269. New York: Springer. } \seealso{ \code{\link{worstErrors}}, \code{\link{plot.qv}}. } \author{ David Firth, \email{d.firth@warwick.ac.uk} } \keyword{models} \keyword{regression} qvcalc/man/worstErrors.Rd0000644000176200001440000000313414744767504015163 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/worstErrors.R \name{worstErrors} \alias{worstErrors} \title{Accuracy of a Quasi-variance Approximation} \usage{ worstErrors(qv.object) } \arguments{ \item{qv.object}{An object of class \code{qv}} } \value{ A numeric vector of length 2, the worst negative relative error and the worst positive relative error. } \description{ Computes the worst relative error, among all contrasts, for the standard error as derived from a set of quasi variances. For details of the method see Menezes (1999) or Firth and Menezes (2004). } \examples{ ## Overdispersed Poisson loglinear model for ship damage data ## from McCullagh and Nelder (1989), Sec 6.3.2 library(MASS) data(ships) ships$year <- as.factor(ships$year) ships$period <- as.factor(ships$period) shipmodel <- glm(formula = incidents ~ type + year + period, family = quasipoisson, data = ships, subset = (service > 0), offset = log(service)) shiptype.qvs <- qvcalc(shipmodel, "type") summary(shiptype.qvs, digits = 4) worstErrors(shiptype.qvs) } \references{ Firth, D. and Mezezes, R. X. de (2004) Quasi-variances. \emph{Biometrika} \bold{91}, 69--80. \doi{10.1093/biomet/91.1.65} McCullagh, P. and Nelder, J. A. (1989) \emph{Generalized Linear Models}. London: Chapman and Hall. Menezes, R. X. (1999) More useful standard errors for group and factor effects in generalized linear models. \emph{D.Phil. Thesis}, Department of Statistics, University of Oxford. } \seealso{ \code{\link{qvcalc}} } \author{ David Firth, \email{d.firth@warwick.ac.uk} } \keyword{models} \keyword{regression} qvcalc/DESCRIPTION0000644000176200001440000000162314745002002013225 0ustar liggesusersPackage: qvcalc Version: 1.0.4 Date: 2025-01-24 Title: Quasi Variances for Factor Effects in Statistical Models Authors@R: c(person(given = "David", family = "Firth", role = c("aut", "cre"), email = "d.firth@warwick.ac.uk", comment = c(ORCID = "0000-0003-0302-2312"))) Maintainer: David Firth URL: https://davidfirth.github.io/qvcalc/ BugReports: https://github.com/DavidFirth/qvcalc/issues Description: Functions to compute quasi variances and associated measures of approximation error. Suggests: relimp, MASS, testthat (>= 3.0.0) Enhances: psychotools, survival License: GPL-2 | GPL-3 Config/testthat/edition: 3 RoxygenNote: 7.3.2 Encoding: UTF-8 NeedsCompilation: no Packaged: 2025-01-24 19:51:56 UTC; david Author: David Firth [aut, cre] () Repository: CRAN Date/Publication: 2025-01-24 21:20:02 UTC