blob: 0f4e0e9e308c078526863493baca0d49476680c8 [file] [log] [blame]
# File src/library/stats/R/var.test.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2015 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
var.test <- function(x, ...) UseMethod("var.test")
var.test.default <-
function(x, y, ratio = 1,
alternative = c("two.sided", "less", "greater"),
conf.level = 0.95, ...)
{
if (!((length(ratio) == 1L) && is.finite(ratio) && (ratio > 0)))
stop("'ratio' must be a single positive number")
alternative <- match.arg(alternative)
if (!((length(conf.level) == 1L) && is.finite(conf.level) &&
(conf.level > 0) && (conf.level < 1)))
stop("'conf.level' must be a single number between 0 and 1")
DNAME <- paste(deparse(substitute(x)), "and", deparse(substitute(y)))
if (inherits(x, "lm") && inherits(y, "lm")) {
DF.x <- x$df.residual
DF.y <- y$df.residual
V.x <- sum(x$residuals^2) / DF.x
V.y <- sum(y$residuals^2) / DF.y
} else {
x <- x[is.finite(x)]
DF.x <- length(x) - 1L
if (DF.x < 1L)
stop("not enough 'x' observations")
y <- y[is.finite(y)]
DF.y <- length(y) - 1L
if (DF.y < 1L)
stop("not enough 'y' observations")
V.x <- var(x)
V.y <- var(y)
}
ESTIMATE <- V.x / V.y
STATISTIC <- ESTIMATE / ratio
PARAMETER <- c("num df" = DF.x, "denom df" = DF.y)
PVAL <- pf(STATISTIC, DF.x, DF.y)
if (alternative == "two.sided") {
PVAL <- 2 * min(PVAL, 1 - PVAL)
BETA <- (1 - conf.level) / 2
CINT <- c(ESTIMATE / qf(1 - BETA, DF.x, DF.y),
ESTIMATE / qf(BETA, DF.x, DF.y))
}
else if (alternative == "greater") {
PVAL <- 1 - PVAL
CINT <- c(ESTIMATE / qf(conf.level, DF.x, DF.y), Inf)
}
else
CINT <- c(0, ESTIMATE / qf(1 - conf.level, DF.x, DF.y))
names(STATISTIC) <- "F"
names(ESTIMATE) <- names(ratio) <- "ratio of variances"
attr(CINT, "conf.level") <- conf.level
RVAL <- list(statistic = STATISTIC,
parameter = PARAMETER,
p.value = PVAL,
conf.int = CINT,
estimate = ESTIMATE,
null.value = ratio,
alternative = alternative,
method = "F test to compare two variances",
data.name = DNAME)
attr(RVAL, "class") <- "htest"
return(RVAL)
}
var.test.formula <-
function(formula, data, subset, na.action, ...)
{
if(missing(formula)
|| (length(formula) != 3L)
|| (length(attr(terms(formula[-2L]), "term.labels")) != 1L))
stop("'formula' missing or incorrect")
m <- match.call(expand.dots = FALSE)
if(is.matrix(eval(m$data, parent.frame())))
m$data <- as.data.frame(data)
## need stats:: for non-standard evaluation
m[[1L]] <- quote(stats::model.frame)
m$... <- NULL
mf <- eval(m, parent.frame())
DNAME <- paste(names(mf), collapse = " by ")
names(mf) <- NULL
response <- attr(attr(mf, "terms"), "response")
g <- factor(mf[[-response]])
if(nlevels(g) != 2L)
stop("grouping factor must have exactly 2 levels")
DATA <- setNames(split(mf[[response]], g), c("x", "y"))
y <- do.call("var.test", c(DATA, list(...)))
y$data.name <- DNAME
y
}