diff --git a/.Rbuildignore b/.Rbuildignore index a83e7fb..2666e2b 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,5 +1,10 @@ -^GOF\.Rproj$ +^renv$ +^renv\.lock$ +^bootGOF\.Rproj$ ^\.Rproj\.user$ ^_pkgdown\.yml$ ^docs$ ^pkgdown$ +^docker$ +^README\.Rmd$ +design.plantuml diff --git a/.gitignore b/.gitignore index 5b6a065..c833a2c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .Rhistory .RData .Ruserdata +inst/doc diff --git a/DESCRIPTION b/DESCRIPTION index 72ec301..781d39e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ -Package: GOF -Title: Bootstrap based goodness-of-fit tests -Version: 0.0.0.9000 +Package: bootGOF +Title: Bootstrap Based Goodness-of-Fit Tests +Version: 0.1.0 Authors@R: c(person(given = "Marsel", family = "Scheer", @@ -10,10 +10,37 @@ Authors@R: family = "Dikta", role = c("aut"), email = "dikta@fh-aachen.de")) -Description: Bootstrap based goodness-of-fit tests. +Description: Bootstrap based goodness-of-fit tests. It allows + to perform rigorous statistical tests to check if a chosen + model family is correct based on the marked empirical + process. The implemented algorithms are described in + (Dikta and Scheer (2021) ) + and can be applied + to generalized linear models without any further implementation + effort. As far as certain linearity conditions are fulfilled + the resampling scheme are also applicable beyond generalized + linear models. This is reflected in the software architecture + which allows to reuse the resampling scheme by implementing + only certain interfaces for models that are not supported + natively by the package. +Imports: + checkmate (>= 2.0.0), + R6 (>= 2.4.1) License: GPL-3 Encoding: UTF-8 -LazyData: true -RoxygenNote: 7.0.2 -URL: https://github.com/MarselScheer/GOF -BugReports: https://github.com/MarselScheer/GOF/issues +RoxygenNote: 7.1.0 +URL: https://github.com/MarselScheer/bootGOF +BugReports: https://github.com/MarselScheer/bootGOF/issues +Suggests: + testthat, + covr, + roxygen2, + pkgdown, + devtools, + tinytest, + mockery, + knitr, + rmarkdown, + minpack.lm, + MASS +VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 6ae9268..fe19901 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,2 +1,18 @@ # Generated by roxygen2: do not edit by hand +export(GOF_glm_info_extractor) +export(GOF_glm_sim_param) +export(GOF_glm_trainer) +export(GOF_lm_info_extractor) +export(GOF_lm_sim_param) +export(GOF_lm_trainer) +export(GOF_model) +export(GOF_model_info_extractor) +export(GOF_model_resample) +export(GOF_model_simulator) +export(GOF_model_test) +export(GOF_model_trainer) +export(GOF_sim_wild_rademacher) +export(Rn1_CvM) +export(Rn1_KS) +export(Rn1_statistic) diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..748f89f --- /dev/null +++ b/NEWS.md @@ -0,0 +1,8 @@ +Version 0.1.0 +========================= + +* initial release +* classical linear models and GLMs can be tested + out of the box +* interfaces defined and documented in order to + reuse the resampling schemes for other models \ No newline at end of file diff --git a/R/GOF_model.R b/R/GOF_model.R new file mode 100644 index 0000000..6795738 --- /dev/null +++ b/R/GOF_model.R @@ -0,0 +1,115 @@ +##' @title Convenience function for creating a GOF-test for statistical models +##' +##' @description Simplifies the creation of an instance of +##' \link{GOF_model_test}, the actual work horse for performing a +##' goodness-of-fit-test. +##' @param model of class 'lm' or 'glm'. Caution with MASS::glm.nb, see +##' vignette 'New-Models' for more details. +##' @param data see \link{GOF_model_test} +##' @param nmb_boot_samples see \link{GOF_model_test} +##' @param simulator_type either "parameteric" or "semi_parameteric_rademacher" +##' @param y_name see \link{GOF_model_test} +##' @param Rn1_statistic see \link{GOF_model_test} +##' @param gof_model_resample_class no need to change this parameter. Here the +##' class used for resampling the model (\link{GOF_model_resample}) +##' is injected. This parameter simply makes it easier to test the +##' convenience function properly. +##' @param gof_model_test_class no need to change this parameter. Here the +##' class used for performing the GOF test (\link{GOF_model_test}) +##' is injected. This parameter simply makes it easier to test the +##' convenience function properly. +##' @export +##' @return instance of \link{GOF_model_test} +##' @examples +##' set.seed(1) +##' N <- 100 +##' X1 <- rnorm(N) +##' X2 <- rnorm(N) +##' d <- data.frame( +##' y = rpois(n = N, lambda = exp(4 + X1 * 2 + X2 * 6)), +##' x1 = X1, +##' x2 = X2) +##' fit <- glm(y ~ x1, data = d, family = poisson()) +##' mt <- GOF_model( +##' model = fit, +##' data = d, +##' nmb_boot_samples = 100, +##' simulator_type = "parametric", +##' y_name = "y", +##' Rn1_statistic = Rn1_KS$new()) +##' mt$get_pvalue() +##' fit <- glm(y ~ x1 + x2, data = d, family = poisson()) +##' mt <- GOF_model( +##' model = fit, +##' data = d, +##' nmb_boot_samples = 100, +##' simulator_type = "parametric", +##' y_name = "y", +##' Rn1_statistic = Rn1_KS$new()) +##' mt$get_pvalue() +GOF_model <- function(model, + data, + nmb_boot_samples, + simulator_type, + y_name, + Rn1_statistic, + gof_model_resample_class = GOF_model_resample, + gof_model_test_class = GOF_model_test + ) { + checkmate::assert_subset( + x = simulator_type, + choices = c("parametric", "semi_parametric_rademacher")) + checkmate::assert_multi_class(x = model, classes = c("lm", "glm")) + if (inherits(x = model, what = "negbin")) { + warning("The GOF-test requires to refit the model. Refitting MASS::glm.nb can be problematic, see vignette New-Models") + } + + + + simulators <- list( + lm = list( + parametric = GOF_lm_sim_param, + semi_parametric_rademacher = GOF_sim_wild_rademacher), + glm = list( + parametric = GOF_glm_sim_param, + semi_parametric_rademacher = list( + new = function() stop( + paste( + "Ordinary Least Square estimate necessary for semi_parameteric_rademacher.", + "But MLE is used for GLMs." + ))) + ) + ) + + if (inherits(x = model, what = "glm")) { + ms <- simulators[["glm"]][[simulator_type]]$new() + mt <- GOF_glm_trainer$new() + mie <- GOF_glm_info_extractor$new() + } else if (inherits(x = model, what = "lm")) { + mt <- GOF_lm_trainer$new() + mie <- GOF_lm_info_extractor$new() + + if (simulator_type == "parametric") { + ms <- simulators[["lm"]][[simulator_type]]$new() + } else { + ms <- simulators[["lm"]][[simulator_type]]$new( + gof_model_info_extractor = mie + ) + } + } + + model_resample <- gof_model_resample_class$new( + gof_model_simulator = ms, + gof_model_trainer = mt + ) + + ret <- gof_model_test_class$new( + model = model, + data = data, + nmb_boot_samples = nmb_boot_samples, + y_name = y_name, + Rn1_statistic = Rn1_statistic, + gof_model_info_extractor = mie, + gof_model_resample = model_resample) + return(ret) +} diff --git a/R/GOF_model_info_extractor.R b/R/GOF_model_info_extractor.R new file mode 100644 index 0000000..ce3dd0c --- /dev/null +++ b/R/GOF_model_info_extractor.R @@ -0,0 +1,89 @@ +##' @title R6 Class representing model information +##' +##' @description R6 does not offer interfaces. Hence all methods +##' are considered as abstract. +##' @export +GOF_model_info_extractor <- R6::R6Class( + classname = "GOF_model_info_extractor", + public = list( + ##' @description Abstract function that estimates/predicts the + ##' the dependent variable in \code{model} + ##' @param model fitted model + ##' @return estimate/prediction of the dependent variable + ##' fitted by \code{model} + yhat = function(model) { + stop("Abstract method. Needs to be implemented") + }, + ##' @description abstract function that calculates the residuals + ##' on the scale of the dependent variable. + ##' @param model fitted model + ##' @return residuals on the scale of the dependent variable + y_minus_yhat = function(model) { + stop("Abstract method. Needs to be implemented") + }, + ##' @description abstract function that calculates the inner product + ##' of estimated parameters and the independent variables. + ##' @param model fitted model + ##' @return inner product of the estimated parameters and the + ##' independent variables. + beta_x_covariates = function(model) { + stop("Abstract method. Needs to be implemented") + }) + ) + +##' @title Implements the "interface" GOF_model_info_extractor +##' for linear models +##' @description This class is specialized in extracting various information +##' from an object of class "lm" +##' @export +GOF_lm_info_extractor = R6::R6Class( + classname = "GOF_lm_info_extractor", + inherit = GOF_model_info_extractor, + public = list( + ##' @description see \link{GOF_model_info_extractor} + ##' @param model see \link{GOF_model_info_extractor} + ##' @return see \link{GOF_model_info_extractor} + yhat = function(model) { + predict.lm(object = model) + }, + ##' @description see \link{GOF_model_info_extractor} + ##' @param model see \link{GOF_model_info_extractor} + ##' @return see \link{GOF_model_info_extractor} + y_minus_yhat = function(model) { + residuals.lm(object = model) + }, + ##' @description see \link{GOF_model_info_extractor} + ##' @param model see \link{GOF_model_info_extractor} + ##' @return see \link{GOF_model_info_extractor} + beta_x_covariates = function(model) { + predict.lm(object = model) + })) + + +##' @title Implements the "interface" GOF_model_info_extractor for +##' for generalized linear models +##' @description This class is specialized in extracting various information +##' from an object of class "glm" +##' @export +GOF_glm_info_extractor = R6::R6Class( + classname = "GOF_glm_info_extractor", + inherit = GOF_model_info_extractor, + public = list( + ##' @description see \link{GOF_model_info_extractor} + ##' @param model see \link{GOF_model_info_extractor} + ##' @return see \link{GOF_model_info_extractor} + yhat = function(model) { + predict.glm(object = model, type = "response") + }, + ##' @description see \link{GOF_model_info_extractor} + ##' @param model see \link{GOF_model_info_extractor} + ##' @return see \link{GOF_model_info_extractor} + y_minus_yhat = function(model) { + residuals.glm(object = model, type = "response") + }, + ##' @description see \link{GOF_model_info_extractor} + ##' @param model see \link{GOF_model_info_extractor} + ##' @return see \link{GOF_model_info_extractor} + beta_x_covariates = function(model) { + predict.glm(object = model, type = "link") + })) diff --git a/R/GOF_model_resample.R b/R/GOF_model_resample.R new file mode 100644 index 0000000..708c62a --- /dev/null +++ b/R/GOF_model_resample.R @@ -0,0 +1,33 @@ +##' @title R6 Class representing the resampling scheme for +##' Goodness-of-fit-tests for (linear) models +##' +##' @description Class is able to resample model fit, i.e. generate a +##' new data set and refit the model to the new data. +##' @export +GOF_model_resample <- R6::R6Class( + classname = "GOF_model_resample", + public = list( + ##' @param gof_model_simulator an instance that implements \link{GOF_model_simulator} + ##' @param gof_model_trainer an instance that implements \link{GOF_model_trainer} + ##' @return No explicit return + initialize = function(gof_model_simulator, gof_model_trainer) { + private$model_simulator <- gof_model_simulator + private$model_trainer <- gof_model_trainer + }, + ##' @description resamples the dependent variable in \code{data} and refits + ##' \code{model} to that new data set + ##' @param model fitted model based on \code{data} + ##' @param data used to fit \code{model} + ##' @param y_name string specifying the name of the dependent variable + ##' @return a resampled version of \code{model} + resample = function(model, data, y_name) { + data_new <- data + data_new[[y_name]] <- private$model_simulator$resample_y(model = model) + ret <- private$model_trainer$refit(model = model, data = data_new) + return(ret) + }), + private = list( + model_simulator = NULL, + model_trainer = NULL + ) +) diff --git a/R/GOF_model_simulator.R b/R/GOF_model_simulator.R new file mode 100644 index 0000000..5e815b3 --- /dev/null +++ b/R/GOF_model_simulator.R @@ -0,0 +1,92 @@ +##' @title R6 Class representing a generator/resample of the dependent variable +##' +##' @description R6 does not offer interfaces. Hence all methods +##' are considered as abstract. +##' @export +GOF_model_simulator <- R6::R6Class( + classname = "GOF_model_simulator", + public = list( + ##' @description Abstract function that resamples/generates + ##' the dependent variable + ##' @param model fitted model + ##' @return generates the dependent variable according to + ##' the \code{model} + resample_y = function(model) { + stop("Abstract method. Needs to be implemented") + })) + +##' @title Implements the "interface" GOF_model_simulator for +##' for linear models +##' @description after the classical linear model was fitted the +##' normal distribution of the +##' of the dependent variable is fully specified and used here +##' to generate new depenedent variables that follow \code{model} +##' @export +GOF_lm_sim_param <- R6::R6Class( + classname = "GOF_lm_sim_param", + ##' @description generates/resamples the dependent variables based + ##' on the parameteric nature defined by \code{model} + ##' @param model see \link{GOF_model_simulator} + ##' @return see \link{GOF_model_simulator} + public = list( + resample_y = function(model) { + simulate(model)[,1] + })) + + +##' Generates Rademacher distributed random variables +##' +##' @param n number of random variables to be generated +##' @return vector of values following the Rademacher distribution +rrademacher <- function(n) { + ret <- 2 * stats::rbinom(n = n, size = 1, prob = 0.5) - 1 + return(ret) +} + +##' @title Implements the "interface" GOF_model_simulator +##' in a semi-parametric fashion +##' @description This is a model agnostic resampling class, where +##' Rademacher random variables are used to add or substract +##' the residuals from the fitted values. +##' @export +GOF_sim_wild_rademacher <- R6::R6Class( + classname = "GOF_sim_wild_rademacher", + public = list( + ##' @param gof_model_info_extractor the info extractor that is used + ##' to derive the residuals and fitted values for resampling. + initialize = function(gof_model_info_extractor) { + private$model_info_extractor = gof_model_info_extractor + }, + ##' @description a wild bootstrap using Rademacher random + ##' variables to resample the dependent variable + ##' @param model see \link{GOF_model_simulator} + ##' @return see \link{GOF_model_simulator} + resample_y = function(model) { + eps <- private$model_info_extractor$y_minus_yhat(model = model) + yhat <- private$model_info_extractor$yhat(model = model) + r <- rrademacher(n = length(eps)) + ret <- yhat + r * eps + return(ret) + } + ), + private = list( + model_info_extractor = NULL + ) +) + + +##' @title Implements the "interface" GOF_model_simulator for +##' for generalized linear models +##' @description after the GLM was fitted the distribution of the +##' of the dependent variable is fully specified and used here +##' to generate new depenedent variables that follow \code{model} +##' @export +GOF_glm_sim_param <- R6::R6Class( + classname = "GOF_glm_sim_param", + public = list( + ##' @description see \link{GOF_model_simulator} + ##' @param model see \link{GOF_model_simulator} + ##' @return see \link{GOF_model_simulator} + resample_y = function(model) { + simulate(model)[,1] + })) diff --git a/R/GOF_model_test.R b/R/GOF_model_test.R new file mode 100644 index 0000000..b9a107a --- /dev/null +++ b/R/GOF_model_test.R @@ -0,0 +1,108 @@ +##' @title R6 Class representing the Goodness-of-Fit test +##' for (linear) models. +##' @description This class can test the null hypothesis that data follows +##' a particular linear model, i.e. classical linear models, generalized +##' linear models or models of the type \eqn{m(\beta^\top X) + \epsilon}. +##' @export +GOF_model_test <- R6::R6Class( + classname = "GOF_model_test", + public = list( + ##' @param model a fitted model + ##' @param data used to fit \code{model} + ##' @param nmb_boot_samples integer specifying the number of bootstrap + ##' samples to perform + ##' @param y_name string specifying the name of the dependent variable in + ##' in \code{data} + ##' @param Rn1_statistic statistic used to map the marked empirical + ##' process to the real line. Needs to be an instance of the class + ##' that implements \link{Rn1_statistic} + ##' @param gof_model_info_extractor an instance that implements + ##' \link{GOF_model_info_extractor} in order to apply it to + ##' \code{model} + ##' @param gof_model_resample an instance that implements + ##' \link{GOF_model_resample} in order to apply it to + ##' \code{model} + ##' @return An instance of the Class + initialize = function(model, + data, + nmb_boot_samples, + y_name, + Rn1_statistic, + gof_model_info_extractor, + gof_model_resample) { + checkmate::assert_count(x = nmb_boot_samples, positive = TRUE) + private$model_org <- model + private$data_org <- data + private$y_name <- y_name + private$Rn1_statistic <- Rn1_statistic + private$nmb_boot_samples <- nmb_boot_samples + private$model_info_extractor <- gof_model_info_extractor + private$model_resample <- gof_model_resample + private$order_beta_dot_X_org <- order( + private$model_info_extractor$beta_x_covariates(model = private$model_org) + ) + private$Rn1_statistic <- Rn1_statistic + }, + ##' @description calculates the marked empricial process for \code{model} + ##' @return vector ordered by the inner product of the estimated + ##' parameter and the independent variables + get_Rn1_org = function() { + if (is.null(private$Rn1_org)) { + private$Rn1_org <- private$Rn1( + y_minus_yhat = private$model_info_extractor$y_minus_yhat( + model = private$model_org + ), + order_beta_x_covariates = private$order_beta_dot_X_org) + } + return(private$Rn1_org) + }, + ##' @description calculates the marked empricial process for the + ##' resampled versions of \code{model} + ##' @return list of length \code{nmb_boot_samples} where every element + ##' is a vector ordered by the inner product of the estimated + ##' parameter and the dependent variables + get_Rn1_boot = function() { + if (is.null(private$Rn1_boot)) { + private$resample_Rn1() + } + return(private$Rn1_boot) + }, + ##' @description p-value for Goodness-of-Fit-test for \code{model} + ##' @return p-value for the null hypothesis that the dependent variable + ##' was generated according to \code{model} + get_pvalue = function() { + stat_org <- private$Rn1_statistic$calc_statistic(Rn1 = self$get_Rn1_org()) + stat_boot <- sapply( + X = self$get_Rn1_boot(), + FUN = private$Rn1_statistic$calc_statistic + ) + mean(stat_org < stat_boot) + }), + private = list( + nmb_boot_samples = NULL, + model_info_extractor = NULL, + model_resample = NULL, + Rn1_statistic = NULL, + Rn1_boot = NULL, + Rn1_org = NULL, + model_org = NULL, + data_org = NULL, + y_name = NULL, + order_beta_dot_X_org = NULL, + Rn1 = function(y_minus_yhat, order_beta_x_covariates) { + ret <- cumsum(x = y_minus_yhat[order_beta_x_covariates]) + return(ret) + }, + resample_Rn1 = function() { + f <- function(dummy) { + fit_boot <- private$model_resample$resample( + model = private$model_org, + data = private$data_org, + y_name = private$y_name) + Rn1_boot <- private$Rn1( + y_minus_yhat = private$model_info_extractor$y_minus_yhat(model = fit_boot), + order_beta_x_covariates = private$order_beta_dot_X_org) + return(Rn1_boot) + } + private$Rn1_boot <- lapply(X = 1:private$nmb_boot_samples, FUN = f) + })) diff --git a/R/GOF_model_trainer.R b/R/GOF_model_trainer.R new file mode 100644 index 0000000..218b8f7 --- /dev/null +++ b/R/GOF_model_trainer.R @@ -0,0 +1,47 @@ +##' @title R6 Class representing a trainer for fitting models +##' +##' @description R6 does not offer interfaces. Hence all methods +##' are considered as abstract. +##' @export +GOF_model_trainer <- R6::R6Class( + classname = "GOF_model_trainer", + public = list( + ##' @description Abstract function refits the model to + ##' a new data set + ##' @param model fitted model + ##' @param data used for refitting the model + ##' @return \code{model} refitted on \code{data} + refit = function(model, data) { + stop("Abstract method. Needs to be implemented") + })) + + +##' @title Implements the "interface" GOF_model_trainer for +##' for linear models +##' @description refits an object of class "lm" to a new data set +##' @export +GOF_lm_trainer <- R6::R6Class( + classname = "GOF_lm_trainer", + public = list( + ##' @description see \link{GOF_model_trainer} + ##' @param model see \link{GOF_model_trainer} + ##' @param data see \link{GOF_model_trainer} + ##' @return see \link{GOF_model_trainer} + refit = function(model, data) { + update(object = model, data = data) + })) + +##' @title Implements the "interface" GOF_model_trainer for +##' for generalized linear models +##' @description refits an object of class "glm" to a new data set +##' @export +GOF_glm_trainer <- R6::R6Class( + classname = "GOF_glm_trainer", + public = list( + ##' @description see \link{GOF_model_trainer} + ##' @param model see \link{GOF_model_trainer} + ##' @param data see \link{GOF_model_trainer} + ##' @return see \link{GOF_model_trainer} + refit = function(model, data) { + update(object = model, data = data) + })) diff --git a/R/Rn1_statistic.R b/R/Rn1_statistic.R new file mode 100644 index 0000000..69b221c --- /dev/null +++ b/R/Rn1_statistic.R @@ -0,0 +1,54 @@ +##' @title R6 Class representing statistics for marked +##' empirical processes +##' +##' @description R6 does not offer interfaces. Hence all methods +##' are considered as abstract. +##' @export +Rn1_statistic <- R6::R6Class( + classname = "Rn1_statistic", + public = list( + ##' @description Abstract function that calculates the statistic + ##' for a given marked empirical process + ##' @param Rn1 marked empirical process as a double vector + ##' @return statistic based on \code{Rn1} + calc_statistic = function(Rn1) { + stop("Abstract method. Needs to be implemented") + }) + ) + +##' @title Kolmogorov-Smirnov-statistic for marked empirical +##' process +##' +##' @description Implements the "interface" Rn1_statistic +##' @export +Rn1_KS <- R6::R6Class( + classname = "Rn1_KS", + inherit = Rn1_statistic, + public = list( + ##' @description calculates the Kolmogorov-Smirnov-statistic + ##' @param Rn1 see \link{Rn1_statistic} + ##' @return see \link{Rn1_statistic} + calc_statistic = function(Rn1) { + ret <- max(abs(Rn1)) + return(ret) + }) +) + +##' @title Cramer-von-Mises-statistic for marked empirical +##' process +##' +##' @description Implements the "interface" Rn1_statistic +##' @export +Rn1_CvM <- R6::R6Class( + classname = "Rn1_CvM", + inherit = Rn1_statistic, + public = list( + ##' @description calculates the calculates the Cramer-von-Mises + ##' statistic + ##' @param Rn1 see \link{Rn1_statistic} + ##' @return see \link{Rn1_statistic} + calc_statistic = function(Rn1) { + ret <- mean(Rn1^2) + return(ret) + }) + ) diff --git a/README.Rmd b/README.Rmd index f09b028..b82b63b 100644 --- a/README.Rmd +++ b/README.Rmd @@ -16,7 +16,7 @@ knitr::opts_chunk$set( ```{r badges, results='asis', echo=FALSE} suppressPackageStartupMessages(library(badgecreatr)) acc <- "MarselScheer" -repo <- "GOF" +repo <- "bootGOF" branch <- "master" status <- "active" lifecycle <- "experimental" @@ -32,12 +32,61 @@ cat(paste(badges, collapse = " ")) ``` -# GOF +# bootGOF -Bootstrap based goodness-of-fit tests. +Bootstrap based goodness-of-fit tests for (linear) models. +Assume you have fitted a statistical model, e.g. classical linear +model or generalized linear model or a model that follows +$Y = m(\beta^\top X) + \epsilon$. This package allows to perform +a rigorous statistical test to check if the chosen model family is correct. ## Example +First we generate a data-set in order to apply the package. + +```{r} +set.seed(1) +N <- 100 +X1 <- rnorm(N) +X2 <- rnorm(N) +d <- data.frame( + y = rpois(n = N, lambda = exp(4 + X1 * 2 + X2 * 6)), + x1 = X1, + x2 = X2) +``` +Note that both covariates influence the dependent variable $Y$. Taking +only one of the covariates into account obviously leads to a model family +that is not correct and the GOF-test should reveal that: + +```{r} +fit <- glm(y ~ x1, data = d, family = poisson()) + +library(bootGOF) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue() +``` + +On the other hand assuming the correct model family should in general not +be rejected by the GOF-test: + +```{r} +fit <- glm(y ~ x1 + x2, data = d, family = poisson()) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue() +``` + ... ## Installation @@ -45,17 +94,17 @@ Bootstrap based goodness-of-fit tests. You can install it from CRAN ```{r, eval = FALSE} -install.packages("GOF") +install.packages("bootGOF") ``` or github ```{r gh-installation, eval = FALSE} -devtools::install_github("MarselScheer/GOF") +devtools::install_github("MarselScheer/bootGOF") ``` # sessionInfo ```{r} sessionInfo() -``` \ No newline at end of file +``` diff --git a/README.md b/README.md index 5dffb25..1407cbc 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,76 @@ - #> the license What license it uses is not recommended for R packages - [![Build -Status](https://travis-ci.org/MarselScheer/GOF.svg?branch=master)](https://travis-ci.org/MarselScheer/GOF) -[![lifecycle](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) +Status](https://travis-ci.org/MarselScheer/bootGOF.svg?branch=master)](https://travis-ci.org/MarselScheer/bootGOF) +[![lifecycle](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) -[![CRAN\_Status\_Badge\_version\_ago](https://www.r-pkg.org/badges/version-ago/GOF)](https://cran.r-project.org/package=GOF) +[![CRAN\_Status\_Badge\_version\_ago](https://www.r-pkg.org/badges/version-ago/bootGOF)](https://cran.r-project.org/package=bootGOF) [![metacran -downloads](https://cranlogs.r-pkg.org/badges/GOF)](https://cran.r-project.org/package=GOF) -[![license](https://img.shields.io/badge/license-What%20license%20it%20uses-lightgrey.svg)](https://choosealicense.com/) +downloads](https://cranlogs.r-pkg.org/badges/bootGOF)](https://cran.r-project.org/package=bootGOF) +[![license](https://img.shields.io/badge/license-GPL--3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) -# GOF +# bootGOF -Bootstrap based goodness-of-fit tests. +Bootstrap based goodness-of-fit tests for (linear) models. Assume you +have fitted a statistical model, e.g. classical linear model or +generalized linear model or a model that follows +\(Y = m(\beta^\top X) + \epsilon\). This package allows to perform a +rigorous statistical test to check if the chosen model family is +correct. ## Example +First we generate a data-set in order to apply the package. + +``` r +set.seed(1) +N <- 100 +X1 <- rnorm(N) +X2 <- rnorm(N) +d <- data.frame( + y = rpois(n = N, lambda = exp(4 + X1 * 2 + X2 * 6)), + x1 = X1, + x2 = X2) +``` + +Note that both covariates influence the dependent variable \(Y\). Taking +only one of the covariates into account obviously leads to a model +family that is not correct and the GOF-test should reveal that: + +``` r +fit <- glm(y ~ x1, data = d, family = poisson()) + +library(bootGOF) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue() +#> [1] 0 +``` + +On the other hand assuming the correct model family should in general +not be rejected by the GOF-test: + +``` r +fit <- glm(y ~ x1 + x2, data = d, family = poisson()) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue() +#> [1] 0.61 +``` + … ## Installation @@ -27,25 +78,25 @@ Bootstrap based goodness-of-fit tests. You can install it from CRAN ``` r -install.packages("GOF") +install.packages("bootGOF") ``` or github ``` r -devtools::install_github("MarselScheer/GOF") +devtools::install_github("MarselScheer/bootGOF") ``` # sessionInfo ``` r sessionInfo() -#> R version 3.6.2 (2019-12-12) +#> R version 4.0.0 (2020-04-24) #> Platform: x86_64-pc-linux-gnu (64-bit) -#> Running under: Debian GNU/Linux 10 (buster) +#> Running under: Ubuntu 20.04 LTS #> #> Matrix products: default -#> BLAS/LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.3.5.so +#> BLAS/LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so #> #> locale: #> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C @@ -56,14 +107,15 @@ sessionInfo() #> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C #> #> attached base packages: -#> [1] stats graphics grDevices utils datasets methods base +#> [1] stats graphics grDevices datasets utils methods base #> #> other attached packages: -#> [1] badgecreatr_0.2.0 +#> [1] bootGOF_0.1.0 badgecreatr_0.2.0 #> #> loaded via a namespace (and not attached): -#> [1] compiler_3.6.2 magrittr_1.5 tools_3.6.2 htmltools_0.4.0 -#> [5] yaml_2.2.0 Rcpp_1.0.3 stringi_1.4.3 rmarkdown_2.1 -#> [9] knitr_1.26 git2r_0.26.1 stringr_1.4.0 xfun_0.11 -#> [13] digest_0.6.23 rlang_0.4.2 evaluate_0.14 +#> [1] digest_0.6.25 R6_2.4.1 backports_1.1.8 git2r_0.27.1 +#> [5] magrittr_1.5 evaluate_0.14 rlang_0.4.10 stringi_1.4.6 +#> [9] renv_0.10.0 checkmate_2.0.0 rmarkdown_2.3 tools_4.0.0 +#> [13] stringr_1.4.0 xfun_0.15 yaml_2.2.1 compiler_4.0.0 +#> [17] htmltools_0.5.0 knitr_1.29 ``` diff --git a/_pkgdown.yml b/_pkgdown.yml index 1753379..84d0262 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1,6 +1,37 @@ destination: docs -title: GOF -url: http://MarselScheer.github.io/GOF +title: bootGOF +url: http://MarselScheer.github.io/bootGOF template: params: bootswatch: flatly +reference: + - title: "GOF-tests" + - desc: > + Functions for performing the statistical test + - contents: + - GOF_model + - GOF_model_test + - title: "Statistics for the marked empiricial process" + - contents: + - Rn1_statistic + - Rn1_CvM + - Rn1_KS + - title: "Class that holds the bootstrap resampling schema" + - contents: + - GOF_model_resample + - title: "Classes for generating/resampling dependent variable" + - contents: + - GOF_model_simulator + - GOF_glm_sim_param + - GOF_lm_sim_param + - GOF_sim_wild_rademacher + - title: "Classes for refitting a model" + - contents: + - GOF_model_trainer + - GOF_glm_trainer + - GOF_lm_trainer + - title: "Classes extracting information from a model" + - contents: + - GOF_model_info_extractor + - GOF_glm_info_extractor + - GOF_lm_info_extractor diff --git a/GOF.Rproj b/bootGOF.Rproj similarity index 100% rename from GOF.Rproj rename to bootGOF.Rproj diff --git a/design.plantuml b/design.plantuml new file mode 100644 index 0000000..4f4a64e --- /dev/null +++ b/design.plantuml @@ -0,0 +1,47 @@ +@startuml +interface Rn1_statistic { + + {abstract} double calc_statistic(Rn1) +} +Rn1_statistic <|-- Rn1_KS +Rn1_statistic <|-- Rn1_CvM +interface GOF_model_simulator { + + {abstract} resample_y(model) +} +GOF_model_simulator <|-- GOF_lm_sim_param +GOF_model_simulator <|-- GOF_sim_wild_rademacher +GOF_model_simulator <|-- GOF_glm_sim_param +interface GOF_model_trainer { + + {abstract} refit(model, data) +} +GOF_model_trainer <|-- GOF_lm_trainer +GOF_model_trainer <|-- GOF_glm_trainer +interface GOF_model_info_extractor { + + {abstract} double[] yhat(model) + + {abstract} double[] y_minus_yhat(model) + + {abstract} double[] beta_x_covariates(model) +} +GOF_model_info_extractor <|-- GOF_lm_info_extractor +GOF_model_info_extractor <|-- GOF_glm_info_extractor +GOF_model_info_extractor *-- GOF_sim_wild_rademacher +abstract class GOF_model_resample { + - GOF_model_simulator + - GOF_model_trainer + + resample() +} +GOF_model_resample *-- GOF_model_simulator +GOF_model_resample *-- GOF_model_trainer +class GOF_model_test { + - GOF_model_info_exctractor + - GOF_model_resample_skeleton RSS + - Rn1_statistic Rn1_stat + - double[] Rn1_org + - double[] Rn1_boot + - double[] Rn1(y_minus_yhat, order_beta_x_covariates) + + get_Rn1_org() + + get_Rn1_boot() + + get_pvalue() +} +GOF_model_test *-- GOF_model_info_extractor +GOF_model_test *-- GOF_model_resample +GOF_model_test *-- Rn1_statistic +@enduml diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..80ba471 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,25 @@ +FROM rocker/verse:4.0.0 + +RUN apt-get update && apt-get install -y \ + ranger \ + git \ + tig \ + htop \ + emacs \ +# graphviz necessary for dot-programm for instance used +# by plantuml + graphviz \ +# xdg-utils and ff necessary to display +# drake-network-graphs + xdg-utils \ + firefox \ + && ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime \ + && git config --global user.email "scheer@freescience.de" \ + && git config --global user.name "Marsel Scheer" \ + && mv /root/.gitconfig /home/rstudio \ + && chown rstudio:rstudio /home/rstudio/.gitconfig \ + && usermod --shell /bin/bash rstudio \ +# create directory for mounting the host file system + && su -l rstudio -c "mkdir -p /tmp/hostfs" \ + && su -l rstudio -c "ln -s /tmp/hostfs /home/rstudio/hostfs" \ + && su -l rstudio -c "echo RENV_PATHS_ROOT=~/hostfs/renv/ > /home/rstudio/.Renviron" diff --git a/docker/Dockerfile.doom b/docker/Dockerfile.doom new file mode 100644 index 0000000..ee82f48 --- /dev/null +++ b/docker/Dockerfile.doom @@ -0,0 +1,17 @@ +FROM rstudio:4.0.0 + +USER rstudio + +# install and configure doom-emacs +RUN git clone --depth 1 https://github.com/hlissner/doom-emacs ~/.emacs.d \ + && yes | ~/.emacs.d/bin/doom install \ + && mv ~/.doom.d ~/.doom.d.org \ + && git clone https://github.com/MarselScheer/.doom.d.git ~/.doom.d \ + && echo "(package! plantuml-mode)" >> ~/.doom.d/packages.el \ + && ~/.emacs.d/bin/doom sync \ + && echo '(setq plantuml-jar-path "/home/rstudio/hostfs/plantuml.jar")' >> ~/.doom.d/config.el \ + && echo "(setq plantuml-default-exec-mode 'jar)" >> ~/.doom.d/config.el + +# root at the end is need, otherwise +# container stops directly after start?!? +USER root diff --git a/docker/build.sh b/docker/build.sh new file mode 100755 index 0000000..f866322 --- /dev/null +++ b/docker/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sudo docker build -t rstudio:4.0.0 . diff --git a/docker/build_doom.sh b/docker/build_doom.sh new file mode 100755 index 0000000..01ab722 --- /dev/null +++ b/docker/build_doom.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +./build.sh +sudo docker build -t doom_r:4.0.0 -f Dockerfile.doom . diff --git a/docker/start.sh b/docker/start.sh new file mode 100755 index 0000000..34131ef --- /dev/null +++ b/docker/start.sh @@ -0,0 +1,5 @@ +sudo docker run --rm -d -p 8787:8787 -e DISABLE_AUTH=true \ + -v ~/docker_fs:/tmp/hostfs \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + rstudio:4.0.0 + diff --git a/docker/start_doom.sh b/docker/start_doom.sh new file mode 100755 index 0000000..214edd8 --- /dev/null +++ b/docker/start_doom.sh @@ -0,0 +1,15 @@ +sudo docker run --rm -d -p 8787:8787 -e DISABLE_AUTH=true \ + -v ~/docker_fs:/tmp/hostfs \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + doom_r:4.0.0 + +# in order to display doom-emacs on the host: +# echo $DISPLAY +# xhost +local:'containerID' +# docker exec -it containerID /bin/bash +# su -l rstudio +# export DISPLAY= +# emacs + + + diff --git a/docs/404.html b/docs/404.html index 7b8c3f7..ab20d99 100644 --- a/docs/404.html +++ b/docs/404.html @@ -6,31 +6,35 @@ -Page not found (404) • GOF +Page not found (404) • bootGOF - + - + - + + + + + - - + + - + - - + + - - + + @@ -53,7 +57,7 @@ - +
@@ -81,11 +85,29 @@
  • Reference +
  • + +
  • + Changelog
  • + + @@ -120,7 +148,7 @@

    Page not found (404)

    -

    Site built with pkgdown 1.4.1.

    +

    Site built with pkgdown 1.5.1.

    diff --git a/docs/articles/Architecture.html b/docs/articles/Architecture.html new file mode 100644 index 0000000..4ba40b7 --- /dev/null +++ b/docs/articles/Architecture.html @@ -0,0 +1,139 @@ + + + + + + + +Architecture • bootGOF + + + + + + + + + + +
    +
    + + + + +
    +
    + + + + +
    +

    +Class-diagram

    +
    +

    Classdiagram

    +
    +
      +
    • +Rn1_statistics, GOF_model_info_extractor, GOF_model_simulator, GOF_sim_wild_rademacher and GOF_model_trainer follow the strategy pattern
    • +
    • +GOF_model_resample follow the template pattern.
    • +
    +

    Note that the object-oriented concepts are realized via the R6-package and that R6 actually does not have a real interface-functionality or abstract classes.

    +
    +
    + + + +
    + + + +
    + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + diff --git a/docs/articles/Architecture_files/accessible-code-block-0.0.1/empty-anchor.js b/docs/articles/Architecture_files/accessible-code-block-0.0.1/empty-anchor.js new file mode 100644 index 0000000..ca349fd --- /dev/null +++ b/docs/articles/Architecture_files/accessible-code-block-0.0.1/empty-anchor.js @@ -0,0 +1,15 @@ +// Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> +// v0.0.1 +// Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. + +document.addEventListener('DOMContentLoaded', function() { + const codeList = document.getElementsByClassName("sourceCode"); + for (var i = 0; i < codeList.length; i++) { + var linkList = codeList[i].getElementsByTagName('a'); + for (var j = 0; j < linkList.length; j++) { + if (linkList[j].innerHTML === "") { + linkList[j].setAttribute('aria-hidden', 'true'); + } + } + } +}); diff --git a/docs/articles/Architecture_files/figure-html/unnamed-chunk-1-1.png b/docs/articles/Architecture_files/figure-html/unnamed-chunk-1-1.png new file mode 100644 index 0000000..bc76b6f Binary files /dev/null and b/docs/articles/Architecture_files/figure-html/unnamed-chunk-1-1.png differ diff --git a/docs/articles/Architecture_files/figure-html/unnamed-chunk-2-1.png b/docs/articles/Architecture_files/figure-html/unnamed-chunk-2-1.png new file mode 100644 index 0000000..fe13239 Binary files /dev/null and b/docs/articles/Architecture_files/figure-html/unnamed-chunk-2-1.png differ diff --git a/docs/articles/New-Models.html b/docs/articles/New-Models.html new file mode 100644 index 0000000..34c59d4 --- /dev/null +++ b/docs/articles/New-Models.html @@ -0,0 +1,335 @@ + + + + + + + +New-Models • bootGOF + + + + + + + + + + +
    +
    + + + + +
    +
    + + + + +

    Usually, one creates a GOF-model-test-class via the function GOF_model(). But this function is actually a wrapper for the class GOF_model_test. That class needs other classes to work properly. In particular it uses the three interfaces GOF_model_info_extractor, GOF_model_simulator, GOF_model_trainer. In general, objects of class lm or glm can be used with GOF_model. However, there might be situations where one has to overwrite the default behavior. For instance, if you want to apply the methodology to new models or simply because a model fit returned by an R-package does not work properly with the GOF-package. Here we show how to implement the three interfaces for some concret cases.

    +
    +

    +Least square estimates

    +

    Assume we have such a model

    +

    \[ +Y = m(\beta^\top X) + \epsilon +\]

    +

    without any knowledge about \(\epsilon\). Then we could try to estimate the \(\beta\) using a least square estimate and using the GOF-package for check our fitted model. First we generate a data set

    +
    library(bootGOF)
    +set.seed(1)
    +X = runif(n = 200, min = 6, max = 14)
    +d = data.frame(x = X, y = sin(0.5 * X) + rnorm(200, sd = 0.2))
    +plot(y~x, data = d)
    +

    +

    Lets have a short excursion at this point because the plot gives the impression that the following simple model might apply:

    +
    wrong_model = lm(y ~ I(x^2), data = d)
    +

    However, a goodness-of-fit-test rejects this model

    +
    mt <- GOF_model(
    +  data = d,
    +  model = wrong_model,
    +  simulator_type = "parametric",
    +  nmb_boot_samples = 100,
    +  y_name = "y",
    +  Rn1_statistic = Rn1_KS$new())
    +mt$get_pvalue()
    +#> [1] 0
    +

    Note that in this simple case the standard diagnostic plots also reveal that this model is not a sufficient. Now we fit the model using a least square estimator:

    +
    library(minpack.lm)
    +fit <- minpack.lm::nlsLM(y ~ sin(a * x),
    +  data = d,
    +  start = c(a = 0.5),
    +  control = nls.control(maxiter = 500))
    +fit
    +#> Nonlinear regression model
    +#>   model: y ~ sin(a * x)
    +#>    data: d
    +#>      a 
    +#> 0.4993 
    +#>  residual sum-of-squares: 7.873
    +#> 
    +#> Number of iterations to convergence: 3 
    +#> Achieved convergence tolerance: 1.49e-08
    +

    In order to create a goodnes-of-fit-test using GOF_model_test we have to implement three interfaces. The first interface requires that we implement three functions yhat, y_minus_yhat and beta_x_covariates, which are the predictions for the dependent variable (also called target-variable), the residuals on the scale of the dependent variable and the inner product of the estimated parameters and the independent variables (also called covariates or features). However, the object returned by minpack.lm::nlsLM does not contain the original data set but that data set is necessary to calculate the inner product. Hence, we make a list that contains the model fit and the data that was used to fit the model.

    +
    fit_and_data <- list(fit = fit, data = d)
    +

    Now we can implement the interface

    +
    library(R6)
    +my_nls_info_extractor <- R6::R6Class(
    +  classname = "my_nls_info_extractor",
    +  inherit = GOF_model_info_extractor,
    +  public = list(
    +    yhat = function(model) {
    +      predict(object = model$fit)
    +    },
    +    y_minus_yhat = function(model) {
    +      residuals(object = model$fit)
    +    },
    +    beta_x_covariates = function(model) {
    +      a_hat <- coef(object = model$fit)
    +      x <- model$data$x
    +      ret <- a_hat * x
    +      return(ret)
    +    }
    +  ))
    +my_info_extractor <- my_nls_info_extractor$new()
    +

    Implementing yhat and y_minus_yhat is straight forward using the function already offered by R but beta_x_covariates needs special attention. The reason is that minpack.lm::nlsLM can also fit very general models of the type \(m(\beta, X)\). Hence, there is now built-in-function to extract objects like \(\beta^\top X\). Lets look at the first few data points:

    +
    head(d)
    +#>           x          y
    +#> 1  8.124069 -0.9199426
    +#> 2  8.976991 -0.9666172
    +#> 3 10.582827 -1.0191812
    +#> 4 13.265662  0.3741709
    +#> 5  7.613455 -0.7480823
    +#> 6 13.187117  0.6588717
    +

    Now we are able to predict \(y\):

    +
    head(my_info_extractor$yhat(model = fit_and_data))
    +#> [1] -0.7926252 -0.9737135 -0.8407826  0.3343611 -0.6132205  0.2971500
    +

    And calculate the difference between \(y\) and our prediction:

    +
    head(my_info_extractor$y_minus_yhat(model = fit_and_data))
    +#> [1] -0.127317499  0.007096259 -0.178398577  0.039809752 -0.134861797
    +#> [6]  0.361721696
    +

    And based on the estimated coefficient we can calculate the inner product with \(x\):

    +
    head(my_info_extractor$beta_x_covariates(model = fit_and_data))
    +#> [1] 4.056695 4.482596 5.284458 6.624113 3.801724 6.584892
    +

    Since we did not make an assumption about the distribution of \(\epsilon\) we cannot use a parametric resampling scheme. However, we can do a wild bootstrap that uses only the predictions and the residuals. The class GOF_sim_wild_rademacher implements this wild bootstrap but needs an info extractor to obtain the preditions and residuals:

    +
    my_simulator <- GOF_sim_wild_rademacher$new(
    +  gof_model_info_extractor = my_info_extractor
    +)
    +

    This class generates as many observations (according to the fitted model) as are contained in the data set used to fit the model.

    +

    Again looking at first at the original data points:

    +
    head(d)
    +#>           x          y
    +#> 1  8.124069 -0.9199426
    +#> 2  8.976991 -0.9666172
    +#> 3 10.582827 -1.0191812
    +#> 4 13.265662  0.3741709
    +#> 5  7.613455 -0.7480823
    +#> 6 13.187117  0.6588717
    +

    Now lets look at new \(y\)s generated according to the fitted model, i.e. following a negative binomial distribution subject to the independent variables:

    +
    head(my_simulator$resample_y(model = fit_and_data))
    +#> [1] -0.6653077 -0.9808097 -1.0191812  0.3741709 -0.4783588  0.6588717
    +

    Note that the resampled \(y\)’s sometimes equal the observed \(y\). The reason is that the this wild bootstrap performs ‘predictions +/- residual’ and only the sign is drawn at random.

    +

    Finally, we need to implement the interface GOF_model_trainer which requires a function refit that is able to update the model object by refitting it to a new data set. R already provides the necessary function, i.e. stats::update. However we combined the fitted model with the data set in a list and we need to take into account:

    +
    my_nls_trainer <- R6::R6Class(
    +  classname = "GOF_nls_trainer",
    +  inherit = GOF_model_trainer,
    +  public = list(
    +    refit = function(model, data) {
    +      fit <- update(object = model$fit, data = data)
    +      ret <- list(fit = fit, data = data)
    +      return(ret)
    +    }))
    +my_trainer <- my_nls_trainer$new()
    +

    This implementation basically equals the implementation of GOF_lm/glm/_trainer. The only difference is that we again store the data with the fit because nlsLM() doesn’t do it for us.

    +

    Of course, fitting the model again to the original data set results in the same fitted model. With the defined classes we can now easily generate a new data set and refit the model to that new data set.

    +
    new_data <- d
    +new_data$y <- my_simulator$resample_y(model = fit_and_data)
    +my_trainer$refit(model = fit_and_data, data = new_data)$fit
    +#> Nonlinear regression model
    +#>   model: y ~ sin(a * x)
    +#>    data: data
    +#>      a 
    +#> 0.4997 
    +#>  residual sum-of-squares: 7.871
    +#> 
    +#> Number of iterations to convergence: 2 
    +#> Achieved convergence tolerance: 1.49e-08
    +

    Now all ingredients are available for applying the Goodness-of-Fit test:

    +
    set.seed(1)
    +mt <- GOF_model_test$new(
    +  model = fit_and_data,
    +  data = d,
    +  nmb_boot_samples = 100,
    +  y_name = "y",
    +  Rn1_statistic = Rn1_CvM$new(),
    +  gof_model_info_extractor = my_info_extractor,
    +  gof_model_resample = GOF_model_resample$new(
    +    gof_model_simulator = my_simulator,
    +    gof_model_trainer = my_trainer
    +  )
    +)
    +mt$get_pvalue()
    +#> [1] 0.8
    +
    +
    +

    +Negative Binomial using the MASS-package

    +

    A negative binomial model is a generalized linear model. Furthermore, within R MASS::glm.nb returns an object of class glm and this package actually can process glm-classes. However, MASS::glm.nb seems to have a bug that prevents to propoerly update/refit such an object via the stats::update() function. We briefly illustrate this using an artificial data set:

    +
    library(MASS)
    +set.seed(1)
    +X1 <- rnorm(100)
    +X2 <- rnorm(100)
    +d <- data.frame(
    +  y = MASS::rnegbin(n = 100, mu = exp(0.2 + X1 * 0.2 + X2 * 0.6), theta = 2),
    +  x1 = X1,
    +  x2 = X2)
    +fit <- MASS::glm.nb(y~x1+x2, data = d)
    +fit
    +#> 
    +#> Call:  MASS::glm.nb(formula = y ~ x1 + x2, data = d, init.theta = 1.561918046, 
    +#>     link = log)
    +#> 
    +#> Coefficients:
    +#> (Intercept)           x1           x2  
    +#>      0.1905       0.1532       0.7696  
    +#> 
    +#> Degrees of Freedom: 99 Total (i.e. Null);  97 Residual
    +#> Null Deviance:       144.3 
    +#> Residual Deviance: 102.4     AIC: 317.5
    +

    Note that fit-object shows that the call contained the parameter init.theta which obviously was not provided by us. The problem is that this init.theta parameter is used by stats::update during refitting resampled data. So fitting resampled data and fitting the original data is slightly different from the perspective of the fitting algorithm. To circumvent this problem we can reimplement the corresponding interface as follows:

    +
    my_negbin_trainer <- R6::R6Class(
    +  classname = "GOF_glmnb_trainer",
    +  inherit = GOF_model_trainer,
    +  public = list(
    +    refit = function(model, data) {
    +      MASS::glm.nb(formula = formula(model), data = data)
    +    }))
    +

    This way we ensure that the original data set and resampled data set are fitted in the same way. Now we can create the GOF-test-class using this new refitting-class

    +
    set.seed(1)
    +mt <- GOF_model_test$new(
    +  model = fit,
    +  data = d,
    +  nmb_boot_samples = 100,
    +  y_name = "y",
    +  Rn1_statistic = Rn1_CvM$new(),
    +  gof_model_info_extractor = GOF_glm_info_extractor$new(),
    +  gof_model_resample = GOF_model_resample$new(
    +    gof_model_simulator = GOF_glm_sim_param$new(),
    +    gof_model_trainer = my_negbin_trainer$new()
    +  )
    +)
    +mt$get_pvalue()
    +#> [1] 0.36
    +

    Lets compare the result with the default GOF-test for glm’s

    +
    set.seed(1)
    +mt2 <- GOF_model(
    +  model = fit,
    +  data = d,
    +  nmb_boot_samples = 100,
    +  simulator_type = "parametric",
    +  y_name = "y",
    +  Rn1_statistic = Rn1_CvM$new()
    +)
    +#> Warning in GOF_model(model = fit, data = d, nmb_boot_samples = 100,
    +#> simulator_type = "parametric", : The GOF-test requires to refit the model.
    +#> Refitting MASS::glm.nb can be problematic, see vignette New-Models
    +mt2$get_pvalue()
    +#> [1] 0.36
    +

    In this case the p-values do not differ. However, it could be different in other settings.

    +
    +
    + + + +
    + + + +
    + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + diff --git a/docs/articles/New-Models_files/accessible-code-block-0.0.1/empty-anchor.js b/docs/articles/New-Models_files/accessible-code-block-0.0.1/empty-anchor.js new file mode 100644 index 0000000..ca349fd --- /dev/null +++ b/docs/articles/New-Models_files/accessible-code-block-0.0.1/empty-anchor.js @@ -0,0 +1,15 @@ +// Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> +// v0.0.1 +// Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. + +document.addEventListener('DOMContentLoaded', function() { + const codeList = document.getElementsByClassName("sourceCode"); + for (var i = 0; i < codeList.length; i++) { + var linkList = codeList[i].getElementsByTagName('a'); + for (var j = 0; j < linkList.length; j++) { + if (linkList[j].innerHTML === "") { + linkList[j].setAttribute('aria-hidden', 'true'); + } + } + } +}); diff --git a/docs/articles/New-Models_files/figure-html/unnamed-chunk-2-1.png b/docs/articles/New-Models_files/figure-html/unnamed-chunk-2-1.png new file mode 100644 index 0000000..eef9d16 Binary files /dev/null and b/docs/articles/New-Models_files/figure-html/unnamed-chunk-2-1.png differ diff --git a/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-1.png b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-1.png new file mode 100644 index 0000000..70a7d60 Binary files /dev/null and b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-1.png differ diff --git a/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-2.png b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-2.png new file mode 100644 index 0000000..5801d2e Binary files /dev/null and b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-2.png differ diff --git a/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-3.png b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-3.png new file mode 100644 index 0000000..ea01962 Binary files /dev/null and b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-3.png differ diff --git a/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-4.png b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-4.png new file mode 100644 index 0000000..3a59f85 Binary files /dev/null and b/docs/articles/New-Models_files/figure-html/unnamed-chunk-3-4.png differ diff --git a/docs/articles/class_diagram.svg b/docs/articles/class_diagram.svg new file mode 100644 index 0000000..b91ab2b --- /dev/null +++ b/docs/articles/class_diagram.svg @@ -0,0 +1,87 @@ +Rn1_statisticdouble calc_statistic(Rn1)Rn1_KSRn1_CvMGOF_model_simulatorresample_y(model)GOF_lm_sim_paramGOF_sim_wild_rademacherGOF_glm_sim_paramGOF_model_trainerrefit(model, data)GOF_lm_trainerGOF_glm_trainerGOF_model_info_extractordouble[] yhat(model)double[] y_minus_yhat(model)double[] beta_x_covariates(model)GOF_lm_info_extractorGOF_glm_info_extractorGOF_model_resampleGOF_model_simulatorGOF_model_trainerresample()GOF_model_testGOF_model_info_exctractorGOF_model_resample_skeleton RSSRn1_statistic Rn1_statdouble[] Rn1_orgdouble[] Rn1_bootdouble[] Rn1(y_minus_yhat, order_beta_x_covariates)get_Rn1_org()get_Rn1_boot()get_pvalue() \ No newline at end of file diff --git a/docs/articles/index.html b/docs/articles/index.html new file mode 100644 index 0000000..a663ac9 --- /dev/null +++ b/docs/articles/index.html @@ -0,0 +1,164 @@ + + + + + + + + +Articles • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    All vignettes

    +

    + +
    +
    Architecture
    +
    +
    New-Models
    +
    +
    +
    +
    +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/authors.html b/docs/authors.html index e52f382..a64334e 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -6,27 +6,31 @@ -Authors • GOF +Authors • bootGOF - + - + - + + + + + - - + + - + - - + + @@ -53,7 +57,7 @@ - +
    @@ -81,11 +85,29 @@
  • Reference +
  • + +
  • + Changelog
  • -

    Site built with pkgdown 1.4.1.

    +

    Site built with pkgdown 1.5.1.

    diff --git a/docs/bootstrap-toc.css b/docs/bootstrap-toc.css new file mode 100644 index 0000000..5a85941 --- /dev/null +++ b/docs/bootstrap-toc.css @@ -0,0 +1,60 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ + +/* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ + +/* All levels of nav */ +nav[data-toggle='toc'] .nav > li > a { + display: block; + padding: 4px 20px; + font-size: 13px; + font-weight: 500; + color: #767676; +} +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 19px; + color: #563d7c; + text-decoration: none; + background-color: transparent; + border-left: 1px solid #563d7c; +} +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 18px; + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-left: 2px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} +nav[data-toggle='toc'] .nav .nav > li > a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + font-size: 12px; + font-weight: normal; +} +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 29px; +} +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 28px; + font-weight: 500; +} + +/* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ +nav[data-toggle='toc'] .nav > .active > ul { + display: block; +} diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js new file mode 100644 index 0000000..1cdd573 --- /dev/null +++ b/docs/bootstrap-toc.js @@ -0,0 +1,159 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ +(function() { + 'use strict'; + + window.Toc = { + helpers: { + // return all matching elements in the set, or their descendants + findOrFilter: function($el, selector) { + // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ + // http://stackoverflow.com/a/12731439/358804 + var $descendants = $el.find(selector); + return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); + }, + + generateUniqueIdBase: function(el) { + var text = $(el).text(); + var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); + return anchor || el.tagName.toLowerCase(); + }, + + generateUniqueId: function(el) { + var anchorBase = this.generateUniqueIdBase(el); + for (var i = 0; ; i++) { + var anchor = anchorBase; + if (i > 0) { + // add suffix + anchor += '-' + i; + } + // check if ID already exists + if (!document.getElementById(anchor)) { + return anchor; + } + } + }, + + generateAnchor: function(el) { + if (el.id) { + return el.id; + } else { + var anchor = this.generateUniqueId(el); + el.id = anchor; + return anchor; + } + }, + + createNavList: function() { + return $(''); + }, + + createChildNavList: function($parent) { + var $childList = this.createNavList(); + $parent.append($childList); + return $childList; + }, + + generateNavEl: function(anchor, text) { + var $a = $(''); + $a.attr('href', '#' + anchor); + $a.text(text); + var $li = $('
  • '); + $li.append($a); + return $li; + }, + + generateNavItem: function(headingEl) { + var anchor = this.generateAnchor(headingEl); + var $heading = $(headingEl); + var text = $heading.data('toc-text') || $heading.text(); + return this.generateNavEl(anchor, text); + }, + + // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). + getTopLevel: function($scope) { + for (var i = 1; i <= 6; i++) { + var $headings = this.findOrFilter($scope, 'h' + i); + if ($headings.length > 1) { + return i; + } + } + + return 1; + }, + + // returns the elements for the top level, and the next below it + getHeadings: function($scope, topLevel) { + var topSelector = 'h' + topLevel; + + var secondaryLevel = topLevel + 1; + var secondarySelector = 'h' + secondaryLevel; + + return this.findOrFilter($scope, topSelector + ',' + secondarySelector); + }, + + getNavLevel: function(el) { + return parseInt(el.tagName.charAt(1), 10); + }, + + populateNav: function($topContext, topLevel, $headings) { + var $context = $topContext; + var $prevNav; + + var helpers = this; + $headings.each(function(i, el) { + var $newNav = helpers.generateNavItem(el); + var navLevel = helpers.getNavLevel(el); + + // determine the proper $context + if (navLevel === topLevel) { + // use top level + $context = $topContext; + } else if ($prevNav && $context === $topContext) { + // create a new level of the tree and switch to it + $context = helpers.createChildNavList($prevNav); + } // else use the current $context + + $context.append($newNav); + + $prevNav = $newNav; + }); + }, + + parseOps: function(arg) { + var opts; + if (arg.jquery) { + opts = { + $nav: arg + }; + } else { + opts = arg; + } + opts.$scope = opts.$scope || $(document.body); + return opts; + } + }, + + // accepts a jQuery object, or an options object + init: function(opts) { + opts = this.helpers.parseOps(opts); + + // ensure that the data attribute is in place for styling + opts.$nav.attr('data-toggle', 'toc'); + + var $topContext = this.helpers.createChildNavList(opts.$nav); + var topLevel = this.helpers.getTopLevel(opts.$scope); + var $headings = this.helpers.getHeadings(opts.$scope, topLevel); + this.helpers.populateNav($topContext, topLevel, $headings); + } + }; + + $(function() { + $('nav[data-toggle="toc"]').each(function(i, el) { + var $nav = $(el); + Toc.init($nav); + }); + }); +})(); diff --git a/docs/index.html b/docs/index.html index 8fb02fa..36681a8 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,20 +5,32 @@ -Bootstrap based goodness-of-fit tests • GOF - - - - - - - +Bootstrap Based Goodness-of-Fit Tests • bootGOF + + + + + + + - +
    - -
    +
    -

    Bootstrap based goodness-of-fit tests.

    +bootGOF

    +

    Bootstrap based goodness-of-fit tests for (linear) models. Assume you have fitted a statistical model, e.g. classical linear model or generalized linear model or a model that follows Y = m(βX) + ϵ. This package allows to perform a rigorous statistical test to check if the chosen model family is correct.

    Example

    +

    First we generate a data-set in order to apply the package.

    +
    set.seed(1)
    +N <- 100
    +X1 <- rnorm(N)
    +X2 <- rnorm(N)
    +d <- data.frame(
    +  y = rpois(n = N, lambda = exp(4 + X1 * 2 + X2 * 6)),
    +  x1 = X1,
    +  x2 = X2)
    +

    Note that both covariates influence the dependent variable Y. Taking only one of the covariates into account obviously leads to a model family that is not correct and the GOF-test should reveal that:

    +
    fit <- glm(y ~ x1, data = d, family = poisson())
    +
    +library(bootGOF)
    +mt <- GOF_model(
    +  model = fit,
    +  data = d,
    +  nmb_boot_samples = 100,
    +  simulator_type = "parametric",
    +  y_name = "y",
    +  Rn1_statistic = Rn1_KS$new())
    +mt$get_pvalue()
    +#> [1] 0
    +

    On the other hand assuming the correct model family should in general not be rejected by the GOF-test:

    +
    fit <- glm(y ~ x1 + x2, data = d, family = poisson())
    +mt <- GOF_model(
    +  model = fit,
    +  data = d,
    +  nmb_boot_samples = 100,
    +  simulator_type = "parametric",
    +  y_name = "y",
    +  Rn1_statistic = Rn1_KS$new())
    +mt$get_pvalue()
    +#> [1] 0.61

    Installation

    You can install it from CRAN

    - +
    install.packages("bootGOF")

    or github

    -
    devtools::install_github("MarselScheer/GOF")
    +
    devtools::install_github("MarselScheer/bootGOF")

    sessionInfo

    - +
    sessionInfo()
    +#> R version 4.0.0 (2020-04-24)
    +#> Platform: x86_64-pc-linux-gnu (64-bit)
    +#> Running under: Ubuntu 20.04 LTS
    +#> 
    +#> Matrix products: default
    +#> BLAS/LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so
    +#> 
    +#> locale:
    +#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
    +#>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
    +#>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=C             
    +#>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
    +#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
    +#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
    +#> 
    +#> attached base packages:
    +#> [1] stats     graphics  grDevices datasets  utils     methods   base     
    +#> 
    +#> other attached packages:
    +#> [1] bootGOF_0.1.0     badgecreatr_0.2.0
    +#> 
    +#> loaded via a namespace (and not attached):
    +#>  [1] digest_0.6.25   R6_2.4.1        backports_1.1.8 git2r_0.27.1   
    +#>  [5] magrittr_1.5    evaluate_0.14   rlang_0.4.10    stringi_1.4.6  
    +#>  [9] renv_0.10.0     checkmate_2.0.0 rmarkdown_2.3   tools_4.0.0    
    +#> [13] stringr_1.4.0   xfun_0.15       yaml_2.2.1      compiler_4.0.0 
    +#> [17] htmltools_0.5.0 knitr_1.29
    -
    -

    Site built with pkgdown 1.4.1.

    +

    Site built with pkgdown 1.5.1.

    diff --git a/docs/news/index.html b/docs/news/index.html new file mode 100644 index 0000000..751b359 --- /dev/null +++ b/docs/news/index.html @@ -0,0 +1,171 @@ + + + + + + + + +Changelog • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    +Version 0.1.0 2021-06-24 +

    +
      +
    • initial release
    • +
    • classical linear models and GLMs can be tested out of the box
    • +
    • interfaces defined and documented in order to reuse the resampling schemes for other models
    • +
    +
    +
    + + + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/pkgdown.css b/docs/pkgdown.css index 9145958..c01e592 100644 --- a/docs/pkgdown.css +++ b/docs/pkgdown.css @@ -17,6 +17,10 @@ html, body { height: 100%; } +body { + position: relative; +} + body > .container { display: flex; height: 100%; @@ -67,6 +71,10 @@ summary { margin-top: calc(-60px + 1em); } +dd { + margin-left: 3em; +} + /* Section anchors ---------------------------------*/ a.anchor { @@ -100,29 +108,132 @@ a.anchor { margin-top: -40px; } +/* Navbar submenu --------------------------*/ + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu>.dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover>.dropdown-menu { + display: block; +} + +.dropdown-submenu>a:after { + display: block; + content: " "; + float: right; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 5px 0 5px 5px; + border-left-color: #cccccc; + margin-top: 5px; + margin-right: -10px; +} + +.dropdown-submenu:hover>a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left>.dropdown-menu { + left: -100%; + margin-left: 10px; + border-radius: 6px 0 6px 6px; +} + /* Sidebar --------------------------*/ -#sidebar { +#pkgdown-sidebar { margin-top: 30px; position: -webkit-sticky; position: sticky; top: 70px; } -#sidebar h2 { + +#pkgdown-sidebar h2 { font-size: 1.5em; margin-top: 1em; } -#sidebar h2:first-child { +#pkgdown-sidebar h2:first-child { margin-top: 0; } -#sidebar .list-unstyled li { +#pkgdown-sidebar .list-unstyled li { margin-bottom: 0.5em; } +/* bootstrap-toc tweaks ------------------------------------------------------*/ + +/* All levels of nav */ + +nav[data-toggle='toc'] .nav > li > a { + padding: 4px 20px 4px 6px; + font-size: 1.5rem; + font-weight: 400; + color: inherit; +} + +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 5px; + color: inherit; + border-left: 1px solid #878787; +} + +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 5px; + font-size: 1.5rem; + font-weight: 400; + color: inherit; + border-left: 2px solid #878787; +} + +/* Nav: second level (shown on .active) */ + +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} + +nav[data-toggle='toc'] .nav .nav > li > a { + padding-left: 16px; + font-size: 1.35rem; +} + +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 15px; +} + +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 15px; + font-weight: 500; + font-size: 1.35rem; +} + +/* orcid ------------------------------------------------------------------- */ + .orcid { - height: 16px; + font-size: 16px; + color: #A6CE39; /* margins are required by official ORCID trademark and display guidelines */ margin-left:4px; margin-right:4px; diff --git a/docs/pkgdown.js b/docs/pkgdown.js index 087a762..7e7048f 100644 --- a/docs/pkgdown.js +++ b/docs/pkgdown.js @@ -9,11 +9,6 @@ $('body').css('padding-top', $('.navbar').height() + 10); }); - $('body').scrollspy({ - target: '#sidebar', - offset: 60 - }); - $('[data-toggle="tooltip"]').tooltip(); var cur_path = paths(location.pathname); diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index 07f400c..a3be7bf 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -1,8 +1,11 @@ -pandoc: 2.3.1 -pkgdown: 1.4.1 +pandoc: 2.7.3 +pkgdown: 1.5.1 pkgdown_sha: ~ -articles: [] +articles: + Architecture: Architecture.html + New-Models: New-Models.html +last_built: 2021-09-02T16:08Z urls: - reference: http://MarselScheer.github.io/GOF/reference - article: http://MarselScheer.github.io/GOF/articles + reference: http://MarselScheer.github.io/bootGOF/reference + article: http://MarselScheer.github.io/bootGOF/articles diff --git a/docs/reference/GOF_glm_info_extractor.html b/docs/reference/GOF_glm_info_extractor.html new file mode 100644 index 0000000..718229c --- /dev/null +++ b/docs/reference/GOF_glm_info_extractor.html @@ -0,0 +1,240 @@ + + + + + + + + +Implements the "interface" GOF_model_info_extractor for + for generalized linear models — GOF_glm_info_extractor • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    This class is specialized in extracting various information + from an object of class "glm"

    +
    + + + +

    Super class

    + +

    bootGOF::GOF_model_info_extractor -> GOF_glm_info_extractor

    +

    Methods

    + + +

    Public methods

    + + +

    Inherited methods +
      +
    +
    + +
    +

    Method yhat()

    +

    see GOF_model_info_extractor

    Usage

    +

    GOF_glm_info_extractor$yhat(model)

    + +

    Arguments

    +

    +

    Returns

    +

    see GOF_model_info_extractor

    +


    +

    Method y_minus_yhat()

    +

    see GOF_model_info_extractor

    Usage

    +

    GOF_glm_info_extractor$y_minus_yhat(model)

    + +

    Arguments

    +

    +

    Returns

    +

    see GOF_model_info_extractor

    +


    +

    Method beta_x_covariates()

    +

    see GOF_model_info_extractor

    Usage

    +

    GOF_glm_info_extractor$beta_x_covariates(model)

    + +

    Arguments

    +

    +

    Returns

    +

    see GOF_model_info_extractor

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_glm_info_extractor$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_glm_sim_param.html b/docs/reference/GOF_glm_sim_param.html new file mode 100644 index 0000000..5443ca8 --- /dev/null +++ b/docs/reference/GOF_glm_sim_param.html @@ -0,0 +1,208 @@ + + + + + + + + +Implements the "interface" GOF_model_simulator for + for generalized linear models — GOF_glm_sim_param • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    after the GLM was fitted the distribution of the + of the dependent variable is fully specified and used here + to generate new depenedent variables that follow model

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method resample_y()

    +

    see GOF_model_simulator

    Usage

    +

    GOF_glm_sim_param$resample_y(model)

    + +

    Arguments

    +

    +
    model

    see GOF_model_simulator

    + +

    +

    Returns

    +

    see GOF_model_simulator

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_glm_sim_param$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_glm_trainer.html b/docs/reference/GOF_glm_trainer.html new file mode 100644 index 0000000..1f9a38a --- /dev/null +++ b/docs/reference/GOF_glm_trainer.html @@ -0,0 +1,206 @@ + + + + + + + + +Implements the "interface" GOF_model_trainer for + for generalized linear models — GOF_glm_trainer • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    refits an object of class "glm" to a new data set

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method refit()

    +

    see GOF_model_trainer

    Usage

    +

    GOF_glm_trainer$refit(model, data)

    + +

    Arguments

    +

    +
    model

    see GOF_model_trainer

    + +
    data

    see GOF_model_trainer

    + +

    +

    Returns

    +

    see GOF_model_trainer

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_glm_trainer$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_lm_info_extractor.html b/docs/reference/GOF_lm_info_extractor.html new file mode 100644 index 0000000..b5bf88c --- /dev/null +++ b/docs/reference/GOF_lm_info_extractor.html @@ -0,0 +1,240 @@ + + + + + + + + +Implements the "interface" GOF_model_info_extractor + for linear models — GOF_lm_info_extractor • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    This class is specialized in extracting various information + from an object of class "lm"

    +
    + + + +

    Super class

    + +

    bootGOF::GOF_model_info_extractor -> GOF_lm_info_extractor

    +

    Methods

    + + +

    Public methods

    + + +

    Inherited methods +
      +
    +
    + +
    +

    Method yhat()

    +

    see GOF_model_info_extractor

    Usage

    +

    GOF_lm_info_extractor$yhat(model)

    + +

    Arguments

    +

    +

    Returns

    +

    see GOF_model_info_extractor

    +


    +

    Method y_minus_yhat()

    +

    see GOF_model_info_extractor

    Usage

    +

    GOF_lm_info_extractor$y_minus_yhat(model)

    + +

    Arguments

    +

    +

    Returns

    +

    see GOF_model_info_extractor

    +


    +

    Method beta_x_covariates()

    +

    see GOF_model_info_extractor

    Usage

    +

    GOF_lm_info_extractor$beta_x_covariates(model)

    + +

    Arguments

    +

    +

    Returns

    +

    see GOF_model_info_extractor

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_lm_info_extractor$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_lm_sim_param.html b/docs/reference/GOF_lm_sim_param.html new file mode 100644 index 0000000..0649560 --- /dev/null +++ b/docs/reference/GOF_lm_sim_param.html @@ -0,0 +1,211 @@ + + + + + + + + +Implements the "interface" GOF_model_simulator for + for linear models — GOF_lm_sim_param • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    after the classical linear model was fitted the + normal distribution of the + of the dependent variable is fully specified and used here + to generate new depenedent variables that follow model

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method resample_y()

    +

    generates/resamples the dependent variables based + on the parameteric nature defined by model

    Usage

    +

    GOF_lm_sim_param$resample_y(model)

    + +

    Arguments

    +

    +
    model

    see GOF_model_simulator

    + +

    +

    Returns

    +

    see GOF_model_simulator

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_lm_sim_param$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_lm_sim_wild_rademacher.html b/docs/reference/GOF_lm_sim_wild_rademacher.html new file mode 100644 index 0000000..727fce3 --- /dev/null +++ b/docs/reference/GOF_lm_sim_wild_rademacher.html @@ -0,0 +1,207 @@ + + + + + + + + +Implements the "interface" GOF_model_simulator for + for linear models — GOF_lm_sim_wild_rademacher • GOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Rademacher random variables are used to change +add or substract the residuals from the fitted values

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method resample_y()

    +

    a wild bootstrap using Rademacher random + variables to resample the dependent variable

    Usage

    +

    GOF_lm_sim_wild_rademacher$resample_y(model)

    + +

    Arguments

    +

    +
    model

    see GOF_model_simulator

    + +

    +

    Returns

    +

    see GOF_model_simulator

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_lm_sim_wild_rademacher$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_lm_trainer.html b/docs/reference/GOF_lm_trainer.html new file mode 100644 index 0000000..f267b0f --- /dev/null +++ b/docs/reference/GOF_lm_trainer.html @@ -0,0 +1,206 @@ + + + + + + + + +Implements the "interface" GOF_model_trainer for + for linear models — GOF_lm_trainer • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    refits an object of class "lm" to a new data set

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method refit()

    +

    see GOF_model_trainer

    Usage

    +

    GOF_lm_trainer$refit(model, data)

    + +

    Arguments

    +

    +
    model

    see GOF_model_trainer

    + +
    data

    see GOF_model_trainer

    + +

    +

    Returns

    +

    see GOF_model_trainer

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_lm_trainer$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_model.html b/docs/reference/GOF_model.html new file mode 100644 index 0000000..c3d1e77 --- /dev/null +++ b/docs/reference/GOF_model.html @@ -0,0 +1,254 @@ + + + + + + + + +Convenience function for creating a GOF-test for statistical models — GOF_model • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Simplifies the creation of an instance of + GOF_model_test, the actual work horse for performing a + goodness-of-fit-test.

    +
    + +
    GOF_model(
    +  model,
    +  data,
    +  nmb_boot_samples,
    +  simulator_type,
    +  y_name,
    +  Rn1_statistic,
    +  gof_model_resample_class = GOF_model_resample,
    +  gof_model_test_class = GOF_model_test
    +)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    model

    of class 'lm' or 'glm'. Caution with MASS::glm.nb, see +vignette 'New-Models' for more details.

    data

    see GOF_model_test

    nmb_boot_samples

    see GOF_model_test

    simulator_type

    either "parameteric" or "semi_parameteric_rademacher"

    y_name

    see GOF_model_test

    Rn1_statistic

    see GOF_model_test

    gof_model_resample_class

    no need to change this parameter. Here the +class used for resampling the model (GOF_model_resample) +is injected. This parameter simply makes it easier to test the +convenience function properly.

    gof_model_test_class

    no need to change this parameter. Here the +class used for performing the GOF test (GOF_model_test) +is injected. This parameter simply makes it easier to test the +convenience function properly.

    + +

    Value

    + +

    instance of GOF_model_test

    + +

    Examples

    +
    set.seed(1) +N <- 100 +X1 <- rnorm(N) +X2 <- rnorm(N) +d <- data.frame( + y = rpois(n = N, lambda = exp(4 + X1 * 2 + X2 * 6)), + x1 = X1, + x2 = X2) +fit <- glm(y ~ x1, data = d, family = poisson()) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue()
    #> [1] 0
    fit <- glm(y ~ x1 + x2, data = d, family = poisson()) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue()
    #> [1] 0.61
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_model_info_extractor.html b/docs/reference/GOF_model_info_extractor.html new file mode 100644 index 0000000..2eea30b --- /dev/null +++ b/docs/reference/GOF_model_info_extractor.html @@ -0,0 +1,234 @@ + + + + + + + + +R6 Class representing model information — GOF_model_info_extractor • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    R6 does not offer interfaces. Hence all methods +are considered as abstract.

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method yhat()

    +

    Abstract function that estimates/predicts the + the dependent variable in model

    Usage

    +

    GOF_model_info_extractor$yhat(model)

    + +

    Arguments

    +

    +
    model

    fitted model

    + +

    +

    Returns

    +

    estimate/prediction of the dependent variable + fitted by model

    +


    +

    Method y_minus_yhat()

    +

    abstract function that calculates the residuals + on the scale of the dependent variable.

    Usage

    +

    GOF_model_info_extractor$y_minus_yhat(model)

    + +

    Arguments

    +

    +
    model

    fitted model

    + +

    +

    Returns

    +

    residuals on the scale of the dependent variable

    +


    +

    Method beta_x_covariates()

    +

    abstract function that calculates the inner product + of estimated parameters and the independent variables.

    Usage

    +

    GOF_model_info_extractor$beta_x_covariates(model)

    + +

    Arguments

    +

    +
    model

    fitted model

    + +

    +

    Returns

    +

    inner product of the estimated parameters and the + independent variables.

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_model_info_extractor$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_model_resample.html b/docs/reference/GOF_model_resample.html new file mode 100644 index 0000000..b133cc5 --- /dev/null +++ b/docs/reference/GOF_model_resample.html @@ -0,0 +1,227 @@ + + + + + + + + +R6 Class representing the resampling scheme for +Goodness-of-fit-tests for (linear) models — GOF_model_resample • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Class is able to resample model fit, i.e. generate a + new data set and refit the model to the new data.

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method new()

    + +

    Usage

    +

    GOF_model_resample$new(gof_model_simulator, gof_model_trainer)

    + +

    Arguments

    +

    +
    gof_model_simulator

    an instance that implements GOF_model_simulator

    + +
    gof_model_trainer

    an instance that implements GOF_model_trainer

    + +

    +

    Returns

    +

    No explicit return

    +


    +

    Method resample()

    +

    resamples the dependent variable in data and refits + model to that new data set

    Usage

    +

    GOF_model_resample$resample(model, data, y_name)

    + +

    Arguments

    +

    +
    model

    fitted model based on data

    + +
    data

    used to fit model

    + +
    y_name

    string specifying the name of the dependent variable

    + +

    +

    Returns

    +

    a resampled version of model

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_model_resample$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_model_simulator.html b/docs/reference/GOF_model_simulator.html new file mode 100644 index 0000000..c668dca --- /dev/null +++ b/docs/reference/GOF_model_simulator.html @@ -0,0 +1,205 @@ + + + + + + + + +R6 Class representing a generator/resample of the dependent variable — GOF_model_simulator • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    R6 does not offer interfaces. Hence all methods + are considered as abstract.

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method resample_y()

    +

    Abstract function that resamples/generates + the dependent variable

    Usage

    +

    GOF_model_simulator$resample_y(model)

    + +

    Arguments

    +

    +
    model

    fitted model

    + +

    +

    Returns

    +

    generates the dependent variable according to + the model

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_model_simulator$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_model_test.html b/docs/reference/GOF_model_test.html new file mode 100644 index 0000000..6fb09d3 --- /dev/null +++ b/docs/reference/GOF_model_test.html @@ -0,0 +1,266 @@ + + + + + + + + +R6 Class representing the Goodness-of-Fit test + for (linear) models. — GOF_model_test • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    This class can test the null hypothesis that data follows + a particular linear model, i.e. classical linear models, generalized + linear models or models of the type \(m(\beta^\top X) + \epsilon\).

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method new()

    + +

    Usage

    +

    GOF_model_test$new(
    +  model,
    +  data,
    +  nmb_boot_samples,
    +  y_name,
    +  Rn1_statistic,
    +  gof_model_info_extractor,
    +  gof_model_resample
    +)

    + +

    Arguments

    +

    +
    model

    a fitted model

    + +
    data

    used to fit model

    + +
    nmb_boot_samples

    integer specifying the number of bootstrap +samples to perform

    + +
    y_name

    string specifying the name of the dependent variable in +in data

    + +
    Rn1_statistic

    statistic used to map the marked empirical +process to the real line. Needs to be an instance of the class +that implements Rn1_statistic

    + +
    gof_model_info_extractor

    an instance that implements +GOF_model_info_extractor in order to apply it to +model

    + +
    gof_model_resample

    an instance that implements +GOF_model_resample in order to apply it to +model

    + +

    +

    Returns

    +

    An instance of the Class

    +


    +

    Method get_Rn1_org()

    +

    calculates the marked empricial process for model

    Usage

    +

    GOF_model_test$get_Rn1_org()

    + +

    Returns

    +

    vector ordered by the inner product of the estimated + parameter and the independent variables

    +


    +

    Method get_Rn1_boot()

    +

    calculates the marked empricial process for the + resampled versions of model

    Usage

    +

    GOF_model_test$get_Rn1_boot()

    + +

    Returns

    +

    list of length nmb_boot_samples where every element + is a vector ordered by the inner product of the estimated + parameter and the dependent variables

    +


    +

    Method get_pvalue()

    +

    p-value for Goodness-of-Fit-test for model

    Usage

    +

    GOF_model_test$get_pvalue()

    + +

    Returns

    +

    p-value for the null hypothesis that the dependent variable + was generated according to model

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_model_test$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_model_test_injector.html b/docs/reference/GOF_model_test_injector.html new file mode 100644 index 0000000..df7468c --- /dev/null +++ b/docs/reference/GOF_model_test_injector.html @@ -0,0 +1,199 @@ + + + + + + + + +Creates a GOF-model-test-class — GOF_model_test_injector • GOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Simplifies the creation of a GOF-model-test-class

    +
    + +
    GOF_model_test_injector(
    +  model,
    +  data,
    +  nmb_boot_samples,
    +  simulator_type,
    +  y_name,
    +  Rn1_statistic,
    +  gof_model_resample_class,
    +  gof_model_test_class
    +)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    model

    see GOF_model_test

    data

    see GOF_model_test

    nmb_boot_samples

    see GOF_model_test

    simulator_type

    see GOF_model

    y_name

    see GOF_model_test

    Rn1_statistic

    see GOF_model_test

    gof_model_resample_class

    GOF_model_resample class

    gof_model_test_class

    GOF_model_test class

    + +

    Value

    + +

    instance of GOF_model_test

    + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_model_trainer.html b/docs/reference/GOF_model_trainer.html new file mode 100644 index 0000000..6d5da6b --- /dev/null +++ b/docs/reference/GOF_model_trainer.html @@ -0,0 +1,206 @@ + + + + + + + + +R6 Class representing a trainer for fitting models — GOF_model_trainer • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    R6 does not offer interfaces. Hence all methods +are considered as abstract.

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method refit()

    +

    Abstract function refits the model to + a new data set

    Usage

    +

    GOF_model_trainer$refit(model, data)

    + +

    Arguments

    +

    +
    model

    fitted model

    + +
    data

    used for refitting the model

    + +

    +

    Returns

    +

    model refitted on data

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_model_trainer$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/GOF_sim_wild_rademacher.html b/docs/reference/GOF_sim_wild_rademacher.html new file mode 100644 index 0000000..6dfd41b --- /dev/null +++ b/docs/reference/GOF_sim_wild_rademacher.html @@ -0,0 +1,222 @@ + + + + + + + + +Implements the "interface" GOF_model_simulator + in a semi-parametric fashion — GOF_sim_wild_rademacher • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    This is a model agnostic resampling class, where +Rademacher random variables are used to add or substract +the residuals from the fitted values.

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method new()

    + +

    Usage

    +

    GOF_sim_wild_rademacher$new(gof_model_info_extractor)

    + +

    Arguments

    +

    +
    gof_model_info_extractor

    the info extractor that is used +to derive the residuals and fitted values for resampling.

    + +

    +


    +

    Method resample_y()

    +

    a wild bootstrap using Rademacher random + variables to resample the dependent variable

    Usage

    +

    GOF_sim_wild_rademacher$resample_y(model)

    + +

    Arguments

    +

    +
    model

    see GOF_model_simulator

    + +

    +

    Returns

    +

    see GOF_model_simulator

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    GOF_sim_wild_rademacher$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/Rn1_CvM.html b/docs/reference/Rn1_CvM.html new file mode 100644 index 0000000..0c4482d --- /dev/null +++ b/docs/reference/Rn1_CvM.html @@ -0,0 +1,213 @@ + + + + + + + + +Cramer-von-Mises-statistic for marked empirical + process — Rn1_CvM • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Implements the "interface" Rn1_statistic

    +
    + + + +

    Super class

    + +

    bootGOF::Rn1_statistic -> Rn1_CvM

    +

    Methods

    + + +

    Public methods

    + + +

    Inherited methods +
      +
    +
    + +
    +

    Method calc_statistic()

    +

    calculates the calculates the Cramer-von-Mises + statistic

    Usage

    +

    Rn1_CvM$calc_statistic(Rn1)

    + +

    Arguments

    +

    +
    Rn1

    see Rn1_statistic

    + +

    +

    Returns

    +

    see Rn1_statistic

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    Rn1_CvM$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/Rn1_KS.html b/docs/reference/Rn1_KS.html new file mode 100644 index 0000000..4feff36 --- /dev/null +++ b/docs/reference/Rn1_KS.html @@ -0,0 +1,212 @@ + + + + + + + + +Kolmogorov-Smirnov-statistic for marked empirical + process — Rn1_KS • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Implements the "interface" Rn1_statistic

    +
    + + + +

    Super class

    + +

    bootGOF::Rn1_statistic -> Rn1_KS

    +

    Methods

    + + +

    Public methods

    + + +

    Inherited methods +
      +
    +
    + +
    +

    Method calc_statistic()

    +

    calculates the Kolmogorov-Smirnov-statistic

    Usage

    +

    Rn1_KS$calc_statistic(Rn1)

    + +

    Arguments

    +

    +
    Rn1

    see Rn1_statistic

    + +

    +

    Returns

    +

    see Rn1_statistic

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    Rn1_KS$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/Rn1_statistic.html b/docs/reference/Rn1_statistic.html new file mode 100644 index 0000000..2f5ee37 --- /dev/null +++ b/docs/reference/Rn1_statistic.html @@ -0,0 +1,207 @@ + + + + + + + + +R6 Class representing statistics for marked + empirical processes — Rn1_statistic • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    R6 does not offer interfaces. Hence all methods + are considered as abstract.

    +
    + + + +

    Methods

    + + +

    Public methods

    + + +


    +

    Method calc_statistic()

    +

    Abstract function that calculates the statistic + for a given marked empirical process

    Usage

    +

    Rn1_statistic$calc_statistic(Rn1)

    + +

    Arguments

    +

    +
    Rn1

    marked empirical process as a double vector

    + +

    +

    Returns

    +

    statistic based on Rn1

    +


    +

    Method clone()

    +

    The objects of this class are cloneable with this method.

    Usage

    +

    Rn1_statistic$clone(deep = FALSE)

    + +

    Arguments

    +

    +
    deep

    Whether to make a deep clone.

    + +

    + + + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/index.html b/docs/reference/index.html index 713a3e5..70c5d68 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -6,27 +6,31 @@ - • GOF +Function reference • bootGOF - + - + - + + + + + - - + + - + - - + + @@ -35,7 +39,7 @@ - + @@ -53,7 +57,7 @@ - +
    @@ -81,11 +85,29 @@
  • Reference +
  • + +
  • + Changelog
  • - @@ -132,7 +340,7 @@

    Contents

    -

    Site built with pkgdown 1.4.1.

    +

    Site built with pkgdown 1.5.1.

    diff --git a/docs/reference/not_covered.html b/docs/reference/not_covered.html new file mode 100644 index 0000000..c39a481 --- /dev/null +++ b/docs/reference/not_covered.html @@ -0,0 +1,156 @@ + + + + + + + + +example of a function that is not covered by unit-tests — not_covered • GOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    example of a function that is not covered by unit-tests

    +
    + +
    not_covered()
    + + +

    Value

    + +

    no explicit return value

    + +

    Examples

    +
    not_covered()
    #> NULL
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/rrademacher.html b/docs/reference/rrademacher.html new file mode 100644 index 0000000..b015d17 --- /dev/null +++ b/docs/reference/rrademacher.html @@ -0,0 +1,180 @@ + + + + + + + + +Generates Rademacher distributed random variables — rrademacher • bootGOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Generates Rademacher distributed random variables

    +
    + +
    rrademacher(n)
    + +

    Arguments

    + + + + + + +
    n

    number of random variables to be generated

    + +

    Value

    + +

    vector of values following the Rademacher distribution

    + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 2d0700b..23b5876 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -1,6 +1,63 @@ - http://MarselScheer.github.io/GOF/index.html + http://MarselScheer.github.io/bootGOF/index.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_glm_info_extractor.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_glm_sim_param.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_glm_trainer.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_lm_info_extractor.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_lm_sim_param.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_lm_trainer.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_model.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_model_info_extractor.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_model_resample.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_model_simulator.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_model_test.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_model_trainer.html + + + http://MarselScheer.github.io/bootGOF/reference/GOF_sim_wild_rademacher.html + + + http://MarselScheer.github.io/bootGOF/reference/Rn1_CvM.html + + + http://MarselScheer.github.io/bootGOF/reference/Rn1_KS.html + + + http://MarselScheer.github.io/bootGOF/reference/Rn1_statistic.html + + + http://MarselScheer.github.io/bootGOF/reference/rrademacher.html + + + http://MarselScheer.github.io/bootGOF/articles/Architecture.html + + + http://MarselScheer.github.io/bootGOF/articles/New-Models.html diff --git a/inst/tinytest/test_GOF_model.R b/inst/tinytest/test_GOF_model.R new file mode 100644 index 0000000..3835b4a --- /dev/null +++ b/inst/tinytest/test_GOF_model.R @@ -0,0 +1,332 @@ +dummy_lm_model <- function() { + set.seed(1) + X <- rnorm(10) + Y <- 5 * X + rnorm(10) + d <- data.frame(y = Y, x = X) + fit <- lm(y ~ x, data = d) + ret <- list(fit = fit, X = X, Y = Y, d = d) + return(ret) +} + +dummy_glm_model <- function() { + set.seed(1) + X <- 1:10 + Y <- 1:10 + d <- data.frame(y = Y, x = X) + fit <- glm(y ~ x, data = d, family = poisson()) + ret <- list(fit = fit, X = X, Y = Y, d = d) + return(ret) +} + +GOF_model_resample_dummy <- R6::R6Class( + classname = "dummy", + public = list( + initialize = function(gof_model_simulator, gof_model_trainer) { + })) + +GOF_model_test_dummy <- R6::R6Class( + classname = "dummy", + public = list( + initialize = function(model, + data, + nmb_boot_samples, + y_name, + Rn1_statistic, + gof_model_info_extractor, + gof_model_resample) { + })) + +GOF_model_error_if_fit_class_is_not_lm_or_glm <- function() { + dummy <- dummy_glm_model() + class(dummy$fit) <- "lmglm" + expect_error( + GOF_model( + model = dummy$fit, + nmb_boot_samples = 1, + data = dummy$d, + y_name = "Y", + simulator_type = "parametric", + Rn1_statistic = Rn1_CvM$new()), + pattern = "model.*inherit.*lm.*glm.*but.*has.*lmglm") +} +GOF_model_error_if_fit_class_is_not_lm_or_glm() + +GOF_model_warns_if_MASS_glmnb_is_used <- function() { + X <- 1:10 + Y <- 1:10 + d <- data.frame(y = Y, x = X) + fit <- suppressWarnings(MASS::glm.nb(y ~ x, data = d)) + expect_warning( + GOF_model( + model = fit, + nmb_boot_samples = 1, + data = d, + y_name = "Y", + simulator_type = "parametric", + Rn1_statistic = Rn1_CvM$new()), + pattern = "The GOF-test requires to refit the model. Refitting MASS::glm.nb can be problematic, see vignette New-Models") +} +GOF_model_warns_if_MASS_glmnb_is_used() + +GOF_model_uses_lm_info_extractor <- function() { + dummy_lm <- dummy_lm_model() + + inject_lm_info_extractor <- FALSE + GOF_model_test_spy <- R6::R6Class( + classname = "GOF_model_test", + public = list( + initialize = function(model, + data, + nmb_boot_samples, + y_name, + Rn1_statistic, + gof_model_info_extractor, + gof_model_resample) { + inject_lm_info_extractor <<- inherits( + x = gof_model_info_extractor, + what = "GOF_lm_info_extractor") + })) + + GOF_model( + model = dummy_lm$fit, + simulator_type = "parametric", + gof_model_resample_class = GOF_model_resample_dummy, + gof_model_test_class = GOF_model_test_spy) + expect_true(inject_lm_info_extractor) +} +GOF_model_uses_lm_info_extractor() + +GOF_model_uses_lm_trainer <- function() { + dummy_lm <- dummy_lm_model() + + inject_lm_trainer <- FALSE + GOF_model_resample_spy <- R6::R6Class( + classname = "GOF_model_resample", + public = list( + initialize = function(gof_model_simulator, gof_model_trainer) { + inject_lm_trainer <<- inherits( + x = gof_model_trainer, + what = "GOF_lm_trainer") + })) + + GOF_model( + model = dummy_lm$fit, + simulator_type = "parametric", + gof_model_test_class = GOF_model_test_dummy, + gof_model_resample_class = GOF_model_resample_spy) + expect_true(inject_lm_trainer) +} +GOF_model_uses_lm_trainer() + +GOF_model_uses_lm_parametric_simulator <- function() { + dummy_lm <- dummy_lm_model() + + inject_lm_param_simulator <- FALSE + GOF_model_resample_spy <- R6::R6Class( + classname = "GOF_model_resample", + public = list( + initialize = function(gof_model_simulator, gof_model_trainer) { + inject_lm_param_simulator <<- inherits( + x = gof_model_simulator, + what = "GOF_lm_sim_param") + })) + + GOF_model( + model = dummy_lm$fit, + simulator_type = "parametric", + gof_model_test_class = GOF_model_test_dummy, + gof_model_resample_class = GOF_model_resample_spy) + expect_true(inject_lm_param_simulator) +} +GOF_model_uses_lm_parametric_simulator() + +GOF_model_uses_lm_rademacher_simulator <- function() { + dummy_lm <- dummy_lm_model() + + inject_lm_rademacher_simulator <- FALSE + GOF_model_resample_spy <- R6::R6Class( + classname = "GOF_model_resample", + public = list( + initialize = function(gof_model_simulator, gof_model_trainer) { + inject_lm_rademacher_simulator <<- inherits( + x = gof_model_simulator, + what = "GOF_sim_wild_rademacher") + })) + + GOF_model( + model = dummy_lm$fit, + simulator_type = "semi_parametric_rademacher", + gof_model_test_class = GOF_model_test_dummy, + gof_model_resample_class = GOF_model_resample_spy) + expect_true(inject_lm_rademacher_simulator) +} +GOF_model_uses_lm_rademacher_simulator() + +GOF_model_uses_unknow_simulator_type <- function() { + expect_error( + GOF_model(simulator_type = "sthelse"), + pattern = "simulator_type.*failed") +} +GOF_model_uses_unknow_simulator_type() + +GOF_model_uses_glm_parametric_simulator <- function() { + dummy_glm <- dummy_glm_model() + + inject_glm_param_simulator <- FALSE + GOF_model_resample_spy <- R6::R6Class( + classname = "GOF_model_resample", + public = list( + initialize = function(gof_model_simulator, gof_model_trainer) { + inject_glm_param_simulator <<- inherits( + x = gof_model_simulator, + what = "GOF_glm_sim_param") + })) + + GOF_model( + model = dummy_glm$fit, + simulator_type = "parametric", + gof_model_test_class = GOF_model_test_dummy, + gof_model_resample_class = GOF_model_resample_spy) + expect_true(inject_glm_param_simulator) +} +GOF_model_uses_glm_parametric_simulator() + +GOF_model_uses_glm_info_extractor <- function() { + dummy_glm <- dummy_glm_model() + + inject_glm_info_extractor <- FALSE + GOF_model_test_spy <- R6::R6Class( + classname = "GOF_model_test", + public = list( + initialize = function(model, + data, + nmb_boot_samples, + y_name, + Rn1_statistic, + gof_model_info_extractor, + gof_model_resample) { + inject_glm_info_extractor <<- inherits( + x = gof_model_info_extractor, + what = "GOF_glm_info_extractor") + })) + + GOF_model( + model = dummy_glm$fit, + simulator_type = "parametric", + gof_model_resample_class = GOF_model_resample_dummy, + gof_model_test_class = GOF_model_test_spy) + expect_true(inject_glm_info_extractor) +} +GOF_model_uses_glm_info_extractor() + +GOF_model_uses_glm_trainer <- function() { + dummy_glm <- dummy_glm_model() + + inject_glm_trainer <- FALSE + GOF_model_resample_spy <- R6::R6Class( + classname = "GOF_model_resample", + public = list( + initialize = function(gof_model_simulator, gof_model_trainer) { + inject_glm_trainer <<- inherits( + x = gof_model_trainer, + what = "GOF_glm_trainer") + })) + + GOF_model( + model = dummy_glm$fit, + simulator_type = "parametric", + gof_model_test_class = GOF_model_test_dummy, + gof_model_resample_class = GOF_model_resample_spy) + expect_true(inject_glm_trainer) +} +GOF_model_uses_glm_trainer() + + +GOF_model_expect_small_pvalue <- function() { + set.seed(1) + X1 <- rnorm(100) + X2 <- rnorm(100) + d <- data.frame( + y = rpois(n = 100, lambda = exp(4 + X1 * 2 + X2 * 6)), + x1 = X1) + fit <- glm(y~x1, data = d, family = poisson()) + mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) + + expect_equal(mt$get_pvalue(), 0) + + X1 <- rnorm(100) + d <- data.frame( + y = rnorm(n = 100, mean = 4 + X1^2), + x1 = X1) + fit <- lm(y~x1, data = d) + mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "semi_parametric_rademacher", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) + + expect_equal(mt$get_pvalue(), 0) +} +GOF_model_expect_small_pvalue() + +GOF_model_expect_non_small_pvalue <- function() { + set.seed(1) + X1 <- rnorm(100) + d <- data.frame( + y = rpois(n = 100, lambda = exp(4 + X1 * 2)), + x1 = X1) + fit <- glm(y~x1, data = d, family = poisson()) + mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) + + expect_equal(mt$get_pvalue(), 0.74) + + X1 <- rnorm(100) + d <- data.frame( + y = rnorm(n = 100, mean = 4 + X1 + X1^2), + x1 = X1) + fit <- lm(y~x1 + I(x1^2), data = d) + mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "semi_parametric_rademacher", + y_name = "y", + Rn1_statistic = Rn1_CvM$new()) + + expect_equal(mt$get_pvalue(), 0.8) +} +GOF_model_expect_non_small_pvalue() + +GOF_model_error_for_glm_semi_parametric <- function() { + set.seed(1) + X1 <- rnorm(100) + d <- data.frame( + y = rpois(n = 100, lambda = exp(4 + X1 * 2)), + x1 = X1) + fit <- glm(y~x1, data = d, family = poisson()) + expect_error( + GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "semi_parametric_rademacher", + y_name = "y", + Rn1_statistic = Rn1_KS$new()), + pattern = "Ordinary Least Square estimate necessary for semi_parameteric_rademacher" + ) +} +GOF_model_error_for_glm_semi_parametric() diff --git a/inst/tinytest/test_GOF_model_info_extractor.R b/inst/tinytest/test_GOF_model_info_extractor.R new file mode 100644 index 0000000..4fa3249 --- /dev/null +++ b/inst/tinytest/test_GOF_model_info_extractor.R @@ -0,0 +1,49 @@ +GOF_model_info_extractor_all_methods_are_abstract <- function() { + mif <- GOF_model_info_extractor$new() + expect_error( + mif$yhat(model = list()), + pattern = "Abstract") + expect_error( + mif$y_minus_yhat(model = list()), + pattern = "Abstract") + expect_error( + mif$beta_x_covariates(model = list()), + pattern = "Abstract") + +} +GOF_model_info_extractor_all_methods_are_abstract() + +GOF_lm_info_extractor_one_covariate <- function() { + fit <- lm(y~x, data = data.frame(y = 2*(1:10), x = 1:10)) + mif <- GOF_lm_info_extractor$new() + expect_equivalent( + mif$yhat(model = fit), + 2 * (1:10)) + expect_equivalent( + mif$y_minus_yhat(model = fit), + replicate(n = 10, expr = 0)) + expect_equivalent( + mif$beta_x_covariates(model = fit), + 2 * (1:10)) +} +GOF_lm_info_extractor_one_covariate() + + +GOF_glm_info_extractor_one_covariate <- function() { + Y <- 2 * (1:10) + X = 1:10 + fit <- glm(y~x, data = data.frame(y = Y, x = X), family = poisson()) + beta <- coef(fit) + b_times_x <- beta["(Intercept)"] + beta["x"] * X + mif <- GOF_glm_info_extractor$new() + expect_equivalent( + mif$yhat(model = fit), + exp(b_times_x)) + expect_equivalent( + mif$y_minus_yhat(model = fit), + Y - exp(b_times_x)) + expect_equivalent( + mif$beta_x_covariates(model = fit), + b_times_x) +} +GOF_glm_info_extractor_one_covariate() diff --git a/inst/tinytest/test_GOF_model_resample.R b/inst/tinytest/test_GOF_model_resample.R new file mode 100644 index 0000000..855bb35 --- /dev/null +++ b/inst/tinytest/test_GOF_model_resample.R @@ -0,0 +1,17 @@ +GOF_model_resample_works <- function() { + d <- data.frame(y = 101:110, x = 1:10) + ms_mock <- R6::R6Class( + inherit = GOF_model_simulator, + public = list( + resample_y = function(model) { + 1:10 + }))$new() + mt <- GOF_lm_trainer$new() + mr <- GOF_model_resample$new(gof_model_simulator = ms_mock, gof_model_trainer = mt) + fit <- lm(y~x, data = d) + fit_new <- mr$resample(model = fit, data = d, y_name = "y") + expect_equivalent( + coef(fit_new), + c(0, 1)) +} +GOF_model_resample_works() diff --git a/inst/tinytest/test_GOF_model_simulator.R b/inst/tinytest/test_GOF_model_simulator.R new file mode 100644 index 0000000..ade7d07 --- /dev/null +++ b/inst/tinytest/test_GOF_model_simulator.R @@ -0,0 +1,104 @@ +GOF_model_simulator_all_methods_abstract <- function() { + ms <- GOF_model_simulator$new() + expect_error( + ms$resample_y(), + pattern = "Abstract") +} +GOF_model_simulator_all_methods_abstract() + +GOF_lm_sim_param_simulates <- function() { + set.seed(1) + ms <- GOF_lm_sim_param$new() + X <- 1:1000 + Y <- X + rnorm(1000, sd = 0.1) + d <- data.frame(y = Y, x = X) + fit <- lm(y~x, data = d) + expect_true( + # epsilon in Y and in resample_y() have a variance + # of 0.1^2, so the difference has an expected + # variance of 2 * 0.1^2 + var(ms$resample_y(model = fit) - Y) <= 2 * 0.1^2 + 0.03 + ) +} +GOF_lm_sim_param_simulates() + +GOF_sim_wild_rademacher_simulates <- function() { + info_mock <- R6::R6Class( + classname = "info_mock", + inherit = GOF_model_info_extractor, + public = list( + yhat = function(model) { + return(1:5) + }, + y_minus_yhat = function(model) { + return(-2:2) + } + ) + ) + info_mock = info_mock$new() + ms <- GOF_sim_wild_rademacher$new(gof_model_info_extractor = info_mock) + mockery::stub( + where = ms$resample_y, + what = "rrademacher", + how = rep(1, 5) + ) + out <- ms$resample_y(model = 5) + expect_equivalent(out, 1:5 + -2:2) + mockery::stub( + where = ms$resample_y, + what = "rrademacher", + how = rep(0, 5) + ) + out <- ms$resample_y(model = list()) + expect_equivalent(out, 1:5) +} +GOF_sim_wild_rademacher_simulates() + +GOF_lm_sim_param_wild_rademacher_simulates <- function() { + set.seed(1) + ie <- GOF_lm_info_extractor$new() + ms <- GOF_sim_wild_rademacher$new(gof_model_info_extractor = ie) + X <- 1:10 + Y <- X + rnorm(10) + d <- data.frame(y = Y, x = X) + fit <- lm(y~x, data = d) + mockery::stub( + where = ms$resample_y, + what = "rrademacher", + how = rep(1, 10) + ) + expect_equivalent( + ms$resample_y(model = fit), + Y + ) + mockery::stub( + where = ms$resample_y, + what = "rrademacher", + how = rep(-1, 10) + ) + expect_equivalent( + ms$resample_y(model = fit), + predict.lm(fit) - residuals.lm(fit) + ) +} +GOF_lm_sim_param_wild_rademacher_simulates() + +GOF_glm_sim_param_simulates <- function() { + set.seed(1) + N <- 100 + X1 <- rnorm(N) + X2 <- rnorm(N) + d <- data.frame( + sth = rpois(n = N, lambda = exp(4 + X1 * 2 + X2 * 6)), + x1 = X1, x2 = X2) + fit <- glm(sth ~ ., data = d, family = poisson()) + ms <- GOF_glm_sim_param$new() + d_sim <- d + d_sim$sth <- ms$resample_y(model = fit) + fit_sim <- glm(sth ~ ., data = d_sim, family = poisson()) + expect_true( + sum(abs(coef(fit) - coef(fit_sim))) <= 0.001 + ) +} +GOF_glm_sim_param_simulates() + diff --git a/inst/tinytest/test_GOF_model_test.R b/inst/tinytest/test_GOF_model_test.R new file mode 100644 index 0000000..e846360 --- /dev/null +++ b/inst/tinytest/test_GOF_model_test.R @@ -0,0 +1,240 @@ +Rn1_fun <- function(r, o) { + cumsum(r[o]) +} +GOF_model_test_necessary_input <- function() { + expect_error( + GOF_model_test$new(), + pattern = "nmb_boot_samples") + expect_error( + GOF_model_test$new(nmb_boot_samples = 0), + pattern = ".*nmb_boot_samples.*>= 1") + expect_error( + GOF_model_test$new( + nmb_boot_samples = 1), + pattern = "model") + expect_error( + GOF_model_test$new( + model = "dummy", + nmb_boot_samples = 1), + pattern = "data") + expect_error( + GOF_model_test$new( + model = "dummy", + nmb_boot_samples = 1, + data = "dummy"), + pattern = "y_name") + expect_error( + GOF_model_test$new( + model = "dummy", + nmb_boot_samples = 1, + data = "dummy", + y_name = "dummy"), + pattern = "Rn1_statistic") + expect_error( + GOF_model_test$new( + model = "dummy", + nmb_boot_samples = 1, + data = "dummy", + y_name = "dummy", + Rn1_statistic = "dummy"), + pattern = "gof_model_info_extractor") + expect_error( + GOF_model_test$new( + model = "dummy", + nmb_boot_samples = 1, + data = "dummy", + y_name = "dummy", + Rn1_statistic = "dummy", + gof_model_info_extractor = "dummy"), + pattern = "gof_model_resample") +} +GOF_model_test_necessary_input() + +GOF_model_test_calc_Rn1_org <- function() { + set.seed(1) + X <- rnorm(10) + Y <- 5 * X + rnorm(10) + d <- data.frame(y = Y, x = X) + fit <- lm(y ~ x, data = d) + mt <- GOF_model_test$new( + model = fit, + data = d, + y_name = "y", + Rn1_statistic = "dummy", + nmb_boot_samples = 10, + gof_model_info_extractor = GOF_lm_info_extractor$new(), + gof_model_resample = "dummy") + expect_equal( + mt$get_Rn1_org(), + Rn1_fun(r = residuals(fit), o = order(X)) + ) +} +GOF_model_test_calc_Rn1_org() + +GOF_model_test_calc_Rn1_boot <- function() { + set.seed(1) + X <- rnorm(10) + Y <- 5 * X + rnorm(10) + d <- data.frame(y = Y, x = X) + fit <- lm(y ~ x, data = d) + + + model_resample_mock <- list(rnorm(10), rnorm(10), rnorm(10)) + MODEL_MOCK_NMB <- 0 + lm_sim_para_mock <- R6::R6Class( + public = list( + resample_y = function(model) { + MODEL_MOCK_NMB <<- MODEL_MOCK_NMB + 1 + model_resample_mock[[MODEL_MOCK_NMB]] + }))$new() + + mt <- GOF_model_test$new( + model = fit, + nmb_boot_samples = 3, + data = d, + y_name = "y", + Rn1_statistic = "dummy", + gof_model_info_extractor = GOF_lm_info_extractor$new(), + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = lm_sim_para_mock, + gof_model_trainer = GOF_lm_trainer$new() + ) + ) + + d1 <- d + d1$y <- model_resample_mock[[1]] + fit1 <- lm(y~x, data = d1) + d2 <- d + d2$y <- model_resample_mock[[2]] + fit2 <- lm(y~x, data = d2) + d3 <- d + d3$y <- model_resample_mock[[3]] + fit3 <- lm(y~x, data = d3) + out <- mt$get_Rn1_boot() + expect_equal( + out, + list( + Rn1_fun(r = residuals(fit1), o = order(X)), + Rn1_fun(r = residuals(fit2), o = order(X)), + Rn1_fun(r = residuals(fit3), o = order(X)) + )) +} +GOF_model_test_calc_Rn1_boot() + +GOF_model_test_calc_pvalue <- function() { + set.seed(1) + X <- rnorm(10) + Y <- 5 * X + rnorm(10) + d <- data.frame(y = Y, x = X) + fit <- lm(y ~ x, data = d) + KS <- Rn1_KS$new() + mt <- GOF_model_test$new( + model = fit, + data = d, + y_name = "y", + Rn1_statistic = KS, + nmb_boot_samples = 10, + gof_model_info_extractor = GOF_lm_info_extractor$new(), + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = GOF_lm_sim_param$new(), + gof_model_trainer = GOF_lm_trainer$new())) + out <- mt$get_pvalue() + expect_equal( + out, + { + stat_org <- KS$calc_statistic(mt$get_Rn1_org()) + stat_boot <- sapply(mt$get_Rn1_boot(), KS$calc_statistic) + mean(stat_org < stat_boot) + } + ) +} +GOF_model_test_calc_pvalue() + + + +GOF_model_test_expect_small_pvalue <- function() { + set.seed(1) + X1 <- rnorm(100) + X2 <- rnorm(100) + d <- data.frame( + y = rpois(n = 100, lambda = exp(4 + X1 * 2 + X2 * 6)), + x1 = X1) + fit <- glm(y~x1, data = d, family = poisson()) + mt <- GOF_model_test$new( + model = fit, + data = d, + y_name = "y", + Rn1_statistic = Rn1_KS$new(), + nmb_boot_samples = 100, + gof_model_info_extractor = GOF_glm_info_extractor$new(), + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = GOF_glm_sim_param$new(), + gof_model_trainer = GOF_glm_trainer$new())) + + expect_equal(mt$get_pvalue(), 0) + + X1 <- rnorm(100) + d <- data.frame( + y = rnorm(n = 100, mean = 4 + X1^2), + x1 = X1) + fit <- lm(y~x1, data = d) + ie <- GOF_lm_info_extractor$new() + mt <- GOF_model_test$new( + model = fit, + data = d, + y_name = "y", + Rn1_statistic = Rn1_KS$new(), + nmb_boot_samples = 100, + gof_model_info_extractor = ie, + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = GOF_sim_wild_rademacher$new( + gof_model_info_extractor = ie + ), + gof_model_trainer = GOF_lm_trainer$new())) + + expect_equal(mt$get_pvalue(), 0) +} +GOF_model_test_expect_small_pvalue() + +GOF_model_test_expect_non_small_pvalue <- function() { + set.seed(1) + X1 <- rnorm(100) + d <- data.frame( + y = rpois(n = 100, lambda = exp(4 + X1 * 2)), + x1 = X1) + fit <- glm(y~x1, data = d, family = poisson()) + mt <- GOF_model_test$new( + model = fit, + data = d, + y_name = "y", + Rn1_statistic = Rn1_KS$new(), + nmb_boot_samples = 100, + gof_model_info_extractor = GOF_glm_info_extractor$new(), + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = GOF_glm_sim_param$new(), + gof_model_trainer = GOF_glm_trainer$new())) + + expect_equal(mt$get_pvalue(), 0.74) + + X1 <- rnorm(100) + d <- data.frame( + y = rnorm(n = 100, mean = 4 + X1 + X1^2), + x1 = X1) + fit <- lm(y~x1 + I(x1^2), data = d) + ie <- GOF_lm_info_extractor$new() + mt <- GOF_model_test$new( + model = fit, + data = d, + y_name = "y", + Rn1_statistic = Rn1_CvM$new(), + nmb_boot_samples = 100, + gof_model_info_extractor = ie, + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = GOF_sim_wild_rademacher$new( + gof_model_info_extractor = ie + ), + gof_model_trainer = GOF_lm_trainer$new())) + + expect_equal(mt$get_pvalue(), 0.8) +} +GOF_model_test_expect_non_small_pvalue() diff --git a/inst/tinytest/test_GOF_model_trainer.R b/inst/tinytest/test_GOF_model_trainer.R new file mode 100644 index 0000000..9dc8baf --- /dev/null +++ b/inst/tinytest/test_GOF_model_trainer.R @@ -0,0 +1,33 @@ +GOF_model_trainer_all_methods_abstract <- function() { + mt <- GOF_model_trainer$new() + expect_error( + mt$refit(), + pattern = "Abstract") +} +GOF_model_trainer_all_methods_abstract() + +GOF_lm_trainer_refits_model <- function() { + mt <- GOF_lm_trainer$new() + d <- data.frame(Y = 1:10, X = 1:10) + fit <- lm(Y~X, data = d) + d_new <- d + d_new$Y <- -(1:10) + fit_new <- mt$refit(model = fit, data = d_new) + expect_equivalent( + coef(fit_new), + c(0, -1)) +} +GOF_lm_trainer_refits_model() + +GOF_glm_trainer_refits_model <- function() { + mt <- GOF_glm_trainer$new() + d <- data.frame(Y = 1:10, X = 1:10) + fit <- glm(Y~X, data = d, family = Gamma()) + d_new <- d + d_new$Y <- (101:110) + fit_new <- mt$refit(model = fit, data = d_new) + expect_equivalent( + coef(fit_new), + coef(glm(Y~X, data = d_new, family = Gamma()))) +} +GOF_glm_trainer_refits_model() diff --git a/inst/tinytest/test_Rn1_statistic.R b/inst/tinytest/test_Rn1_statistic.R new file mode 100644 index 0000000..f3d59c9 --- /dev/null +++ b/inst/tinytest/test_Rn1_statistic.R @@ -0,0 +1,26 @@ +Rn1_statistic_all_methods_are_abstract <- function() { + stat <- Rn1_statistic$new() + expect_error( + stat$calc_statistic(Rn1 = 1:100), + pattern = "Abstract") + +} +Rn1_statistic_all_methods_are_abstract() + +Rn1_KS_calculates_Kolomogorov_Smirnoff <- function() { + stat <- Rn1_KS$new() + r <- runif(10) + expect_equal( + stat$calc_statistic(Rn1 = r), + max(r)) +} +Rn1_KS_calculates_Kolomogorov_Smirnoff() + +Rn1_CvM_calculates_Cramer_von_Mises <- function() { + stat <- Rn1_CvM$new() + r <- runif(10) + expect_equal( + stat$calc_statistic(Rn1 = r), + mean(r^2)) +} +Rn1_CvM_calculates_Cramer_von_Mises() diff --git a/man/GOF_glm_info_extractor.Rd b/man/GOF_glm_info_extractor.Rd new file mode 100644 index 0000000..6583b84 --- /dev/null +++ b/man/GOF_glm_info_extractor.Rd @@ -0,0 +1,106 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_info_extractor.R +\name{GOF_glm_info_extractor} +\alias{GOF_glm_info_extractor} +\title{Implements the "interface" GOF_model_info_extractor for + for generalized linear models} +\description{ +This class is specialized in extracting various information + from an object of class "glm" +} +\section{Super class}{ +\code{\link[bootGOF:GOF_model_info_extractor]{bootGOF::GOF_model_info_extractor}} -> \code{GOF_glm_info_extractor} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-yhat}{\code{GOF_glm_info_extractor$yhat()}} +\item \href{#method-y_minus_yhat}{\code{GOF_glm_info_extractor$y_minus_yhat()}} +\item \href{#method-beta_x_covariates}{\code{GOF_glm_info_extractor$beta_x_covariates()}} +\item \href{#method-clone}{\code{GOF_glm_info_extractor$clone()}} +} +} +\if{html}{ +\out{
    Inherited methods} +\itemize{ +} +\out{
    } +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-yhat}{}}} +\subsection{Method \code{yhat()}}{ +see \link{GOF_model_info_extractor} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_info_extractor$yhat(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_info_extractor}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_info_extractor} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-y_minus_yhat}{}}} +\subsection{Method \code{y_minus_yhat()}}{ +see \link{GOF_model_info_extractor} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_info_extractor$y_minus_yhat(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_info_extractor}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_info_extractor} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-beta_x_covariates}{}}} +\subsection{Method \code{beta_x_covariates()}}{ +see \link{GOF_model_info_extractor} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_info_extractor$beta_x_covariates(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_info_extractor}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_info_extractor} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_info_extractor$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_glm_sim_param.Rd b/man/GOF_glm_sim_param.Rd new file mode 100644 index 0000000..23e4425 --- /dev/null +++ b/man/GOF_glm_sim_param.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_simulator.R +\name{GOF_glm_sim_param} +\alias{GOF_glm_sim_param} +\title{Implements the "interface" GOF_model_simulator for + for generalized linear models} +\description{ +after the GLM was fitted the distribution of the + of the dependent variable is fully specified and used here + to generate new depenedent variables that follow \code{model} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-resample_y}{\code{GOF_glm_sim_param$resample_y()}} +\item \href{#method-clone}{\code{GOF_glm_sim_param$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-resample_y}{}}} +\subsection{Method \code{resample_y()}}{ +see \link{GOF_model_simulator} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_sim_param$resample_y(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_simulator}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_simulator} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_sim_param$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_glm_trainer.Rd b/man/GOF_glm_trainer.Rd new file mode 100644 index 0000000..57e1a19 --- /dev/null +++ b/man/GOF_glm_trainer.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_trainer.R +\name{GOF_glm_trainer} +\alias{GOF_glm_trainer} +\title{Implements the "interface" GOF_model_trainer for + for generalized linear models} +\description{ +refits an object of class "glm" to a new data set +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-refit}{\code{GOF_glm_trainer$refit()}} +\item \href{#method-clone}{\code{GOF_glm_trainer$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-refit}{}}} +\subsection{Method \code{refit()}}{ +see \link{GOF_model_trainer} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_trainer$refit(model, data)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_trainer}} + +\item{\code{data}}{see \link{GOF_model_trainer}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_trainer} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_glm_trainer$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_lm_info_extractor.Rd b/man/GOF_lm_info_extractor.Rd new file mode 100644 index 0000000..de0008e --- /dev/null +++ b/man/GOF_lm_info_extractor.Rd @@ -0,0 +1,106 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_info_extractor.R +\name{GOF_lm_info_extractor} +\alias{GOF_lm_info_extractor} +\title{Implements the "interface" GOF_model_info_extractor + for linear models} +\description{ +This class is specialized in extracting various information + from an object of class "lm" +} +\section{Super class}{ +\code{\link[bootGOF:GOF_model_info_extractor]{bootGOF::GOF_model_info_extractor}} -> \code{GOF_lm_info_extractor} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-yhat}{\code{GOF_lm_info_extractor$yhat()}} +\item \href{#method-y_minus_yhat}{\code{GOF_lm_info_extractor$y_minus_yhat()}} +\item \href{#method-beta_x_covariates}{\code{GOF_lm_info_extractor$beta_x_covariates()}} +\item \href{#method-clone}{\code{GOF_lm_info_extractor$clone()}} +} +} +\if{html}{ +\out{
    Inherited methods} +\itemize{ +} +\out{
    } +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-yhat}{}}} +\subsection{Method \code{yhat()}}{ +see \link{GOF_model_info_extractor} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_info_extractor$yhat(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_info_extractor}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_info_extractor} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-y_minus_yhat}{}}} +\subsection{Method \code{y_minus_yhat()}}{ +see \link{GOF_model_info_extractor} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_info_extractor$y_minus_yhat(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_info_extractor}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_info_extractor} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-beta_x_covariates}{}}} +\subsection{Method \code{beta_x_covariates()}}{ +see \link{GOF_model_info_extractor} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_info_extractor$beta_x_covariates(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_info_extractor}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_info_extractor} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_info_extractor$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_lm_sim_param.Rd b/man/GOF_lm_sim_param.Rd new file mode 100644 index 0000000..61a824b --- /dev/null +++ b/man/GOF_lm_sim_param.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_simulator.R +\name{GOF_lm_sim_param} +\alias{GOF_lm_sim_param} +\title{Implements the "interface" GOF_model_simulator for + for linear models} +\description{ +after the classical linear model was fitted the + normal distribution of the + of the dependent variable is fully specified and used here + to generate new depenedent variables that follow \code{model} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-resample_y}{\code{GOF_lm_sim_param$resample_y()}} +\item \href{#method-clone}{\code{GOF_lm_sim_param$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-resample_y}{}}} +\subsection{Method \code{resample_y()}}{ +generates/resamples the dependent variables based + on the parameteric nature defined by \code{model} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_sim_param$resample_y(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_simulator}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_simulator} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_sim_param$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_lm_trainer.Rd b/man/GOF_lm_trainer.Rd new file mode 100644 index 0000000..c8b6c50 --- /dev/null +++ b/man/GOF_lm_trainer.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_trainer.R +\name{GOF_lm_trainer} +\alias{GOF_lm_trainer} +\title{Implements the "interface" GOF_model_trainer for + for linear models} +\description{ +refits an object of class "lm" to a new data set +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-refit}{\code{GOF_lm_trainer$refit()}} +\item \href{#method-clone}{\code{GOF_lm_trainer$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-refit}{}}} +\subsection{Method \code{refit()}}{ +see \link{GOF_model_trainer} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_trainer$refit(model, data)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_trainer}} + +\item{\code{data}}{see \link{GOF_model_trainer}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_trainer} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_lm_trainer$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_model.Rd b/man/GOF_model.Rd new file mode 100644 index 0000000..0bbbaf3 --- /dev/null +++ b/man/GOF_model.Rd @@ -0,0 +1,77 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model.R +\name{GOF_model} +\alias{GOF_model} +\title{Convenience function for creating a GOF-test for statistical models} +\usage{ +GOF_model( + model, + data, + nmb_boot_samples, + simulator_type, + y_name, + Rn1_statistic, + gof_model_resample_class = GOF_model_resample, + gof_model_test_class = GOF_model_test +) +} +\arguments{ +\item{model}{of class 'lm' or 'glm'. Caution with MASS::glm.nb, see +vignette 'New-Models' for more details.} + +\item{data}{see \link{GOF_model_test}} + +\item{nmb_boot_samples}{see \link{GOF_model_test}} + +\item{simulator_type}{either "parameteric" or "semi_parameteric_rademacher"} + +\item{y_name}{see \link{GOF_model_test}} + +\item{Rn1_statistic}{see \link{GOF_model_test}} + +\item{gof_model_resample_class}{no need to change this parameter. Here the +class used for resampling the model (\link{GOF_model_resample}) +is injected. This parameter simply makes it easier to test the +convenience function properly.} + +\item{gof_model_test_class}{no need to change this parameter. Here the +class used for performing the GOF test (\link{GOF_model_test}) +is injected. This parameter simply makes it easier to test the +convenience function properly.} +} +\value{ +instance of \link{GOF_model_test} +} +\description{ +Simplifies the creation of an instance of + \link{GOF_model_test}, the actual work horse for performing a + goodness-of-fit-test. +} +\examples{ +set.seed(1) +N <- 100 +X1 <- rnorm(N) +X2 <- rnorm(N) +d <- data.frame( + y = rpois(n = N, lambda = exp(4 + X1 * 2 + X2 * 6)), + x1 = X1, + x2 = X2) +fit <- glm(y ~ x1, data = d, family = poisson()) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue() +fit <- glm(y ~ x1 + x2, data = d, family = poisson()) +mt <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue() +} diff --git a/man/GOF_model_info_extractor.Rd b/man/GOF_model_info_extractor.Rd new file mode 100644 index 0000000..d6cb296 --- /dev/null +++ b/man/GOF_model_info_extractor.Rd @@ -0,0 +1,101 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_info_extractor.R +\name{GOF_model_info_extractor} +\alias{GOF_model_info_extractor} +\title{R6 Class representing model information} +\description{ +R6 does not offer interfaces. Hence all methods +are considered as abstract. +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-yhat}{\code{GOF_model_info_extractor$yhat()}} +\item \href{#method-y_minus_yhat}{\code{GOF_model_info_extractor$y_minus_yhat()}} +\item \href{#method-beta_x_covariates}{\code{GOF_model_info_extractor$beta_x_covariates()}} +\item \href{#method-clone}{\code{GOF_model_info_extractor$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-yhat}{}}} +\subsection{Method \code{yhat()}}{ +Abstract function that estimates/predicts the + the dependent variable in \code{model} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_info_extractor$yhat(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{fitted model} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +estimate/prediction of the dependent variable + fitted by \code{model} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-y_minus_yhat}{}}} +\subsection{Method \code{y_minus_yhat()}}{ +abstract function that calculates the residuals + on the scale of the dependent variable. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_info_extractor$y_minus_yhat(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{fitted model} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +residuals on the scale of the dependent variable +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-beta_x_covariates}{}}} +\subsection{Method \code{beta_x_covariates()}}{ +abstract function that calculates the inner product + of estimated parameters and the independent variables. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_info_extractor$beta_x_covariates(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{fitted model} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +inner product of the estimated parameters and the + independent variables. +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_info_extractor$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_model_resample.Rd b/man/GOF_model_resample.Rd new file mode 100644 index 0000000..09141c0 --- /dev/null +++ b/man/GOF_model_resample.Rd @@ -0,0 +1,82 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_resample.R +\name{GOF_model_resample} +\alias{GOF_model_resample} +\title{R6 Class representing the resampling scheme for +Goodness-of-fit-tests for (linear) models} +\description{ +Class is able to resample model fit, i.e. generate a + new data set and refit the model to the new data. +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-new}{\code{GOF_model_resample$new()}} +\item \href{#method-resample}{\code{GOF_model_resample$resample()}} +\item \href{#method-clone}{\code{GOF_model_resample$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-new}{}}} +\subsection{Method \code{new()}}{ +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_resample$new(gof_model_simulator, gof_model_trainer)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{gof_model_simulator}}{an instance that implements \link{GOF_model_simulator}} + +\item{\code{gof_model_trainer}}{an instance that implements \link{GOF_model_trainer}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +No explicit return +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-resample}{}}} +\subsection{Method \code{resample()}}{ +resamples the dependent variable in \code{data} and refits + \code{model} to that new data set +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_resample$resample(model, data, y_name)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{fitted model based on \code{data}} + +\item{\code{data}}{used to fit \code{model}} + +\item{\code{y_name}}{string specifying the name of the dependent variable} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +a resampled version of \code{model} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_resample$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_model_simulator.Rd b/man/GOF_model_simulator.Rd new file mode 100644 index 0000000..28eff07 --- /dev/null +++ b/man/GOF_model_simulator.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_simulator.R +\name{GOF_model_simulator} +\alias{GOF_model_simulator} +\title{R6 Class representing a generator/resample of the dependent variable} +\description{ +R6 does not offer interfaces. Hence all methods + are considered as abstract. +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-resample_y}{\code{GOF_model_simulator$resample_y()}} +\item \href{#method-clone}{\code{GOF_model_simulator$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-resample_y}{}}} +\subsection{Method \code{resample_y()}}{ +Abstract function that resamples/generates + the dependent variable +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_simulator$resample_y(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{fitted model} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +generates the dependent variable according to + the \code{model} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_simulator$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_model_test.Rd b/man/GOF_model_test.Rd new file mode 100644 index 0000000..20c7baf --- /dev/null +++ b/man/GOF_model_test.Rd @@ -0,0 +1,130 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_test.R +\name{GOF_model_test} +\alias{GOF_model_test} +\title{R6 Class representing the Goodness-of-Fit test + for (linear) models.} +\description{ +This class can test the null hypothesis that data follows + a particular linear model, i.e. classical linear models, generalized + linear models or models of the type \eqn{m(\beta^\top X) + \epsilon}. +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-new}{\code{GOF_model_test$new()}} +\item \href{#method-get_Rn1_org}{\code{GOF_model_test$get_Rn1_org()}} +\item \href{#method-get_Rn1_boot}{\code{GOF_model_test$get_Rn1_boot()}} +\item \href{#method-get_pvalue}{\code{GOF_model_test$get_pvalue()}} +\item \href{#method-clone}{\code{GOF_model_test$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-new}{}}} +\subsection{Method \code{new()}}{ +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_test$new( + model, + data, + nmb_boot_samples, + y_name, + Rn1_statistic, + gof_model_info_extractor, + gof_model_resample +)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{a fitted model} + +\item{\code{data}}{used to fit \code{model}} + +\item{\code{nmb_boot_samples}}{integer specifying the number of bootstrap +samples to perform} + +\item{\code{y_name}}{string specifying the name of the dependent variable in +in \code{data}} + +\item{\code{Rn1_statistic}}{statistic used to map the marked empirical +process to the real line. Needs to be an instance of the class +that implements \link{Rn1_statistic}} + +\item{\code{gof_model_info_extractor}}{an instance that implements +\link{GOF_model_info_extractor} in order to apply it to +\code{model}} + +\item{\code{gof_model_resample}}{an instance that implements +\link{GOF_model_resample} in order to apply it to +\code{model}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +An instance of the Class +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-get_Rn1_org}{}}} +\subsection{Method \code{get_Rn1_org()}}{ +calculates the marked empricial process for \code{model} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_test$get_Rn1_org()}\if{html}{\out{
    }} +} + +\subsection{Returns}{ +vector ordered by the inner product of the estimated + parameter and the independent variables +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-get_Rn1_boot}{}}} +\subsection{Method \code{get_Rn1_boot()}}{ +calculates the marked empricial process for the + resampled versions of \code{model} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_test$get_Rn1_boot()}\if{html}{\out{
    }} +} + +\subsection{Returns}{ +list of length \code{nmb_boot_samples} where every element + is a vector ordered by the inner product of the estimated + parameter and the dependent variables +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-get_pvalue}{}}} +\subsection{Method \code{get_pvalue()}}{ +p-value for Goodness-of-Fit-test for \code{model} +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_test$get_pvalue()}\if{html}{\out{
    }} +} + +\subsection{Returns}{ +p-value for the null hypothesis that the dependent variable + was generated according to \code{model} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_test$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_model_trainer.Rd b/man/GOF_model_trainer.Rd new file mode 100644 index 0000000..e05898e --- /dev/null +++ b/man/GOF_model_trainer.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_trainer.R +\name{GOF_model_trainer} +\alias{GOF_model_trainer} +\title{R6 Class representing a trainer for fitting models} +\description{ +R6 does not offer interfaces. Hence all methods +are considered as abstract. +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-refit}{\code{GOF_model_trainer$refit()}} +\item \href{#method-clone}{\code{GOF_model_trainer$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-refit}{}}} +\subsection{Method \code{refit()}}{ +Abstract function refits the model to + a new data set +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_trainer$refit(model, data)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{fitted model} + +\item{\code{data}}{used for refitting the model} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +\code{model} refitted on \code{data} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_model_trainer$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/GOF_sim_wild_rademacher.Rd b/man/GOF_sim_wild_rademacher.Rd new file mode 100644 index 0000000..17cbdcf --- /dev/null +++ b/man/GOF_sim_wild_rademacher.Rd @@ -0,0 +1,75 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_simulator.R +\name{GOF_sim_wild_rademacher} +\alias{GOF_sim_wild_rademacher} +\title{Implements the "interface" GOF_model_simulator + in a semi-parametric fashion} +\description{ +This is a model agnostic resampling class, where +Rademacher random variables are used to add or substract +the residuals from the fitted values. +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-new}{\code{GOF_sim_wild_rademacher$new()}} +\item \href{#method-resample_y}{\code{GOF_sim_wild_rademacher$resample_y()}} +\item \href{#method-clone}{\code{GOF_sim_wild_rademacher$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-new}{}}} +\subsection{Method \code{new()}}{ +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_sim_wild_rademacher$new(gof_model_info_extractor)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{gof_model_info_extractor}}{the info extractor that is used +to derive the residuals and fitted values for resampling.} +} +\if{html}{\out{
    }} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-resample_y}{}}} +\subsection{Method \code{resample_y()}}{ +a wild bootstrap using Rademacher random + variables to resample the dependent variable +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_sim_wild_rademacher$resample_y(model)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{model}}{see \link{GOF_model_simulator}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{GOF_model_simulator} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{GOF_sim_wild_rademacher$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/Rn1_CvM.Rd b/man/Rn1_CvM.Rd new file mode 100644 index 0000000..872138c --- /dev/null +++ b/man/Rn1_CvM.Rd @@ -0,0 +1,64 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rn1_statistic.R +\name{Rn1_CvM} +\alias{Rn1_CvM} +\title{Cramer-von-Mises-statistic for marked empirical + process} +\description{ +Implements the "interface" Rn1_statistic +} +\section{Super class}{ +\code{\link[bootGOF:Rn1_statistic]{bootGOF::Rn1_statistic}} -> \code{Rn1_CvM} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-calc_statistic}{\code{Rn1_CvM$calc_statistic()}} +\item \href{#method-clone}{\code{Rn1_CvM$clone()}} +} +} +\if{html}{ +\out{
    Inherited methods} +\itemize{ +} +\out{
    } +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-calc_statistic}{}}} +\subsection{Method \code{calc_statistic()}}{ +calculates the calculates the Cramer-von-Mises + statistic +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{Rn1_CvM$calc_statistic(Rn1)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{Rn1}}{see \link{Rn1_statistic}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{Rn1_statistic} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{Rn1_CvM$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/Rn1_KS.Rd b/man/Rn1_KS.Rd new file mode 100644 index 0000000..994040f --- /dev/null +++ b/man/Rn1_KS.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rn1_statistic.R +\name{Rn1_KS} +\alias{Rn1_KS} +\title{Kolmogorov-Smirnov-statistic for marked empirical + process} +\description{ +Implements the "interface" Rn1_statistic +} +\section{Super class}{ +\code{\link[bootGOF:Rn1_statistic]{bootGOF::Rn1_statistic}} -> \code{Rn1_KS} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-calc_statistic}{\code{Rn1_KS$calc_statistic()}} +\item \href{#method-clone}{\code{Rn1_KS$clone()}} +} +} +\if{html}{ +\out{
    Inherited methods} +\itemize{ +} +\out{
    } +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-calc_statistic}{}}} +\subsection{Method \code{calc_statistic()}}{ +calculates the Kolmogorov-Smirnov-statistic +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{Rn1_KS$calc_statistic(Rn1)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{Rn1}}{see \link{Rn1_statistic}} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +see \link{Rn1_statistic} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{Rn1_KS$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/Rn1_statistic.Rd b/man/Rn1_statistic.Rd new file mode 100644 index 0000000..101f403 --- /dev/null +++ b/man/Rn1_statistic.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rn1_statistic.R +\name{Rn1_statistic} +\alias{Rn1_statistic} +\title{R6 Class representing statistics for marked + empirical processes} +\description{ +R6 does not offer interfaces. Hence all methods + are considered as abstract. +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-calc_statistic}{\code{Rn1_statistic$calc_statistic()}} +\item \href{#method-clone}{\code{Rn1_statistic$clone()}} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-calc_statistic}{}}} +\subsection{Method \code{calc_statistic()}}{ +Abstract function that calculates the statistic + for a given marked empirical process +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{Rn1_statistic$calc_statistic(Rn1)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{Rn1}}{marked empirical process as a double vector} +} +\if{html}{\out{
    }} +} +\subsection{Returns}{ +statistic based on \code{Rn1} +} +} +\if{html}{\out{
    }} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
    }}\preformatted{Rn1_statistic$clone(deep = FALSE)}\if{html}{\out{
    }} +} + +\subsection{Arguments}{ +\if{html}{\out{
    }} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
    }} +} +} +} diff --git a/man/rrademacher.Rd b/man/rrademacher.Rd new file mode 100644 index 0000000..c7c9bd4 --- /dev/null +++ b/man/rrademacher.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GOF_model_simulator.R +\name{rrademacher} +\alias{rrademacher} +\title{Generates Rademacher distributed random variables} +\usage{ +rrademacher(n) +} +\arguments{ +\item{n}{number of random variables to be generated} +} +\value{ +vector of values following the Rademacher distribution +} +\description{ +Generates Rademacher distributed random variables +} diff --git a/renv.lock b/renv.lock new file mode 100644 index 0000000..2d5aa26 --- /dev/null +++ b/renv.lock @@ -0,0 +1,648 @@ +{ + "R": { + "Version": "4.0.0", + "Repositories": [ + { + "Name": "CRAN", + "URL": "https://cloud.r-project.org" + } + ] + }, + "Packages": { + "BH": { + "Package": "BH", + "Version": "1.72.0-3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8f9ce74c6417d61f0782cbae5fd2b7b0" + }, + "DT": { + "Package": "DT", + "Version": "0.14", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "a3580ce0309c94d061c23b0afb4accbd" + }, + "MASS": { + "Package": "MASS", + "Version": "7.3-51.6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "1dad32ac9dbd8057167b2979fb932ff7" + }, + "R6": { + "Package": "R6", + "Version": "2.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "292b54f8f4b94669b08f94e5acce6be2" + }, + "Rcpp": { + "Package": "Rcpp", + "Version": "1.0.4.6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e652f23d8b1807cc975c51410d05b72f" + }, + "XML": { + "Package": "XML", + "Version": "3.99-0.5", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "408d42d1359f2a84d377c1f7f0568624" + }, + "askpass": { + "Package": "askpass", + "Version": "1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e8a22846fff485f0be3770c2da758713" + }, + "assertthat": { + "Package": "assertthat", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "50c838a310445e954bc13f26f26a6ecf" + }, + "backports": { + "Package": "backports", + "Version": "1.1.8", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "3ef0eac19317fd03c0c854aed581d473" + }, + "badgecreatr": { + "Package": "badgecreatr", + "Version": "0.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5db59479f84ad4a0650e74a8d8edac70" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "brew": { + "Package": "brew", + "Version": "1.0-6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "92a5f887f9ae3035ac7afde22ba73ee9" + }, + "callr": { + "Package": "callr", + "Version": "3.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "643163a00cb536454c624883a10ae0bc" + }, + "checkmate": { + "Package": "checkmate", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "a667800d5f0350371bedeb8b8b950289" + }, + "cli": { + "Package": "cli", + "Version": "2.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ff0becff7bfdfe3f75d29aff8f3172dd" + }, + "clipr": { + "Package": "clipr", + "Version": "0.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "08cf4045c149a0f0eaf405324c7495bd" + }, + "commonmark": { + "Package": "commonmark", + "Version": "1.7", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "0f22be39ec1d141fd03683c06f3a6e67" + }, + "covr": { + "Package": "covr", + "Version": "3.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "cbc6df1ef6ee576f844f973c1fc04ab4" + }, + "crayon": { + "Package": "crayon", + "Version": "1.3.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "0d57bc8e27b7ba9e45dba825ebc0de6b" + }, + "crosstalk": { + "Package": "crosstalk", + "Version": "1.1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ae55f5d7c02f0ab43c58dd050694f2b4" + }, + "curl": { + "Package": "curl", + "Version": "4.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "2b7d10581cc730804e9ed178c8374bd6" + }, + "desc": { + "Package": "desc", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6c8fe8fa26a23b79949375d372c7b395" + }, + "devtools": { + "Package": "devtools", + "Version": "2.3.0", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "d55dae3aa077e25128115a81e974f318" + }, + "digest": { + "Package": "digest", + "Version": "0.6.25", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "f697db7d92b7028c4b3436e9603fb636" + }, + "ellipsis": { + "Package": "ellipsis", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "fd2844b3a43ae2d27e70ece2df1b4e2a" + }, + "evaluate": { + "Package": "evaluate", + "Version": "0.14", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ec8ca05cffcc70569eaaad8469d2a3a7" + }, + "fansi": { + "Package": "fansi", + "Version": "0.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "7fce217eaaf8016e72065e85c73027b5" + }, + "fs": { + "Package": "fs", + "Version": "1.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8c04112383ca1988e96f429255f95675" + }, + "gh": { + "Package": "gh", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "89ea5998938d1ad55f035c8a86f96b74" + }, + "git2r": { + "Package": "git2r", + "Version": "0.27.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "531a82d1beed1f545beb25f4f5945bf7" + }, + "glue": { + "Package": "glue", + "Version": "1.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "f43e0d5e85ccb0a4045670c0607ee504" + }, + "grImport": { + "Package": "grImport", + "Version": "0.9-3", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "510ede2a36dd1086c2bdc81715ad449e" + }, + "highlight": { + "Package": "highlight", + "Version": "0.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "88eee986f41177f688ffd11189cb3aec" + }, + "highr": { + "Package": "highr", + "Version": "0.8", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "4dc5bb88961e347a0f4d8aad597cbfac" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "7d651b7131794fe007b1ad6f21aaa401" + }, + "htmlwidgets": { + "Package": "htmlwidgets", + "Version": "1.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "41bace23583fbc25089edae324de2dc3" + }, + "httr": { + "Package": "httr", + "Version": "1.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "7146fea4685b4252ebf478978c75f597" + }, + "ini": { + "Package": "ini", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6154ec2223172bce8162d4153cda21f7" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "1.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "2657f20b9a74c996c602e74ebe540b06" + }, + "knitr": { + "Package": "knitr", + "Version": "1.29", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e5f4c41c17df8cdf7b0df12117c0d99a" + }, + "later": { + "Package": "later", + "Version": "1.1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d0a62b247165aabf397fded504660d8a" + }, + "lazyeval": { + "Package": "lazyeval", + "Version": "0.2.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d908914ae53b04d4c0c0fd72ecc35370" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "0.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "361811f31f71f8a617a9a68bf63f1f42" + }, + "magrittr": { + "Package": "magrittr", + "Version": "1.5", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "1bb58822a20301cee84a41678e25d9b7" + }, + "markdown": { + "Package": "markdown", + "Version": "1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "61e4a10781dd00d7d81dd06ca9b94e95" + }, + "memoise": { + "Package": "memoise", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "58baa74e4603fcfb9a94401c58c8f9b1" + }, + "mime": { + "Package": "mime", + "Version": "0.9", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e87a35ec73b157552814869f45a63aa3" + }, + "mockery": { + "Package": "mockery", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "313fa6504824ba5aab9308412135fb5f" + }, + "openssl": { + "Package": "openssl", + "Version": "1.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "b3209c62052922b6c629544d94c8fa8a" + }, + "pillar": { + "Package": "pillar", + "Version": "1.4.6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "bdf26e55ccb7df3e49a490150277f002" + }, + "pkgbuild": { + "Package": "pkgbuild", + "Version": "1.0.8", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8d8b5e29223aabb829246397299f0592" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "pkgdown": { + "Package": "pkgdown", + "Version": "1.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "df386e7004001a999d1494cb4538c9bc" + }, + "pkgload": { + "Package": "pkgload", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "b6b150cd4709e0c0c9b5d51ac4376282" + }, + "plantuml": { + "Package": "plantuml", + "Version": "0.4", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteUsername": "rkrug", + "RemoteRepo": "plantuml", + "RemoteRef": "master", + "RemoteSha": "4cc45be014152017b840462a2f814e5edb2cb07f", + "Hash": "bef6cceb744345f83e43c6e98a3cf528" + }, + "png": { + "Package": "png", + "Version": "0.1-7", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "03b7076c234cb3331288919983326c55" + }, + "praise": { + "Package": "praise", + "Version": "1.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "a555924add98c99d2f411e37e7d25e9f" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "95ef9167b75dde9d2ccc3c7528393e7e" + }, + "processx": { + "Package": "processx", + "Version": "3.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "f4f13345fcb00c51ace12f65dd18749f" + }, + "promises": { + "Package": "promises", + "Version": "1.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "a8730dcbdd19f9047774909f0ec214a4" + }, + "ps": { + "Package": "ps", + "Version": "1.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "425d938eb9c02906a8ac98c0c2a306b5" + }, + "purrr": { + "Package": "purrr", + "Version": "0.3.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "97def703420c8ab10d8f0e6c72101e02" + }, + "rcmdcheck": { + "Package": "rcmdcheck", + "Version": "1.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ed95895886dab6d2a584da45503555da" + }, + "rematch2": { + "Package": "rematch2", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "76c9e04c712a05848ae7a23d2f170a40" + }, + "remotes": { + "Package": "remotes", + "Version": "2.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "430a0908aee75b1fcba0e62857cab0ce" + }, + "renv": { + "Package": "renv", + "Version": "0.11.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "1c3ef87cbb81c23ac96797781ec7aecc" + }, + "rex": { + "Package": "rex", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "093584b944440c5cd07a696b3c8e0e4c" + }, + "rlang": { + "Package": "rlang", + "Version": "0.4.7", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "c06d2a6887f4b414f8e927afd9ee976a" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "202260e1b2c410edc086d5b8f1ed946e" + }, + "roxygen2": { + "Package": "roxygen2", + "Version": "7.1.0", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "f173062c04dc8e91d7376d914df6efee" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "1.3-2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "f6a407ae5dd21f6f80a6708bbb6eb3ae" + }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.11", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "33a5b27a03da82ac4b1d43268f80088a" + }, + "rversions": { + "Package": "rversions", + "Version": "2.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "0ec41191f744d0f5afad8c6f35cc36e4" + }, + "sessioninfo": { + "Package": "sessioninfo", + "Version": "1.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "308013098befe37484df72c39cf90d6e" + }, + "stringi": { + "Package": "stringi", + "Version": "1.4.6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e99d8d656980d2dd416a962ae55aec90" + }, + "stringr": { + "Package": "stringr", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "0759e6b6c0957edb1311028a49a35e76" + }, + "sys": { + "Package": "sys", + "Version": "3.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "507f3116a38d37ad330a038b3be07b66" + }, + "testthat": { + "Package": "testthat", + "Version": "2.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "0829b987b8961fb07f3b1b64a2fbc495" + }, + "tibble": { + "Package": "tibble", + "Version": "3.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "08bd36bd34b20d4f7971d49e81deaab0" + }, + "tinytest": { + "Package": "tinytest", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "af2182641bc7c5b954f1b6bb56583b45" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.24", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8f24b65b86f4d6d7b1e2d8a4ce2c02fb" + }, + "usethis": { + "Package": "usethis", + "Version": "1.6.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e1985f5a9985fea2e338fa7eb99018ca" + }, + "utf8": { + "Package": "utf8", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "4a5081acfb7b81a572e4384a7aaf2af1" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5ba3006888ac62fd5e97b208d00d3317" + }, + "whisker": { + "Package": "whisker", + "Version": "0.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ca970b96d894e90397ed20637a0c1bbe" + }, + "withr": { + "Package": "withr", + "Version": "2.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ecd17882a0b4419545691e095b74ee89" + }, + "xfun": { + "Package": "xfun", + "Version": "0.15", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ddeca7650052ff9131ac7c41a9a77b3b" + }, + "xml2": { + "Package": "xml2", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d4d71a75dd3ea9eb5fa28cc21f9585e2" + }, + "xopen": { + "Package": "xopen", + "Version": "1.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6c85f015dee9cc7710ddd20f86881f58" + }, + "yaml": { + "Package": "yaml", + "Version": "2.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "2826c5d9efb0a88f657c7a679c7106db" + } + } +} diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..4ea3f11 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,4 @@ +library(testthat) +library(bootGOF) + +test_check("bootGOF") diff --git a/tests/testthat/test-dummy.R b/tests/testthat/test-dummy.R new file mode 100644 index 0000000..8849056 --- /dev/null +++ b/tests/testthat/test-dummy.R @@ -0,0 +1,3 @@ +test_that("multiplication works", { + expect_equal(2 * 2, 4) +}) diff --git a/tests/tinytest.R b/tests/tinytest.R new file mode 100644 index 0000000..e2ca361 --- /dev/null +++ b/tests/tinytest.R @@ -0,0 +1,5 @@ + +if ( requireNamespace("tinytest", quietly=TRUE) ){ + tinytest::test_package("bootGOF") +} + diff --git a/vignettes/.gitignore b/vignettes/.gitignore new file mode 100644 index 0000000..097b241 --- /dev/null +++ b/vignettes/.gitignore @@ -0,0 +1,2 @@ +*.html +*.R diff --git a/vignettes/Architecture.Rmd b/vignettes/Architecture.Rmd new file mode 100644 index 0000000..a6a592e --- /dev/null +++ b/vignettes/Architecture.Rmd @@ -0,0 +1,36 @@ +--- +title: "Architecture" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Architecture} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set(echo = FALSE) +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +# Class-diagram + +```{r, eval = FALSE, echo = FALSE} +suppressMessages(library(plantuml)) +uml_str <- paste(readLines("design.plantuml"), collapse = "\n") +uml <- plantuml::plantuml(x = uml_str) +plot(uml, file = "./vignettes/class_diagram.svg") +``` +![Classdiagram](class_diagram.svg) + +* *Rn1_statistics*, *GOF_model_info_extractor*, *GOF_model_simulator*, + *GOF_sim_wild_rademacher* and *GOF_model_trainer* follow the + strategy pattern +* *GOF_model_resample* follow the template pattern. + +Note that the object-oriented concepts are realized via the +R6-package and that R6 actually does not have a real +interface-functionality or abstract classes. + diff --git a/vignettes/New-Models.Rmd b/vignettes/New-Models.Rmd new file mode 100644 index 0000000..58f53be --- /dev/null +++ b/vignettes/New-Models.Rmd @@ -0,0 +1,328 @@ +--- +title: "New-Models" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{New-Models} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + + +Usually, one creates a GOF-model-test-class via the function +*GOF_model()*. But this function is actually a wrapper for the +class *GOF_model_test*. That class needs other classes to +work properly. In particular it uses the three interfaces +*GOF_model_info_extractor*, *GOF_model_simulator*, +*GOF_model_trainer*. In general, objects of class *lm* or +*glm* can be used with *GOF_model*. However, there might +be situations where one has to overwrite the default +behavior. For instance, if you want to apply the methodology +to new models or simply because a model fit returned by an +R-package does not work properly with the GOF-package. +Here we show how to implement the three interfaces for some +concret cases. + +# Least square estimates + +Assume we have such a model + +$$ +Y = m(\beta^\top X) + \epsilon +$$ + +without any knowledge about $\epsilon$. Then we could +try to estimate the $\beta$ using a least square estimate +and using the GOF-package for check our fitted model. +First we generate a data set + +```{r} +library(bootGOF) +set.seed(1) +X = runif(n = 200, min = 6, max = 14) +d = data.frame(x = X, y = sin(0.5 * X) + rnorm(200, sd = 0.2)) +plot(y~x, data = d) +``` + +Lets have a short excursion at this point because the plot gives +the impression that the following simple model might apply: +```{r} +wrong_model = lm(y ~ I(x^2), data = d) +``` + +However, a goodness-of-fit-test rejects this model + +```{r} +mt <- GOF_model( + data = d, + model = wrong_model, + simulator_type = "parametric", + nmb_boot_samples = 100, + y_name = "y", + Rn1_statistic = Rn1_KS$new()) +mt$get_pvalue() +``` + +Note that in this simple case the standard diagnostic plots +also reveal that this model is not a sufficient. Now we +fit the model using a least square estimator: + +```{r} +library(minpack.lm) +fit <- minpack.lm::nlsLM(y ~ sin(a * x), + data = d, + start = c(a = 0.5), + control = nls.control(maxiter = 500)) +fit +``` + +In order to create a goodnes-of-fit-test using *GOF_model_test* +we have to implement three interfaces. The first interface requires +that we implement three functions *yhat*, *y_minus_yhat* and +*beta_x_covariates*, which are the predictions for the dependent +variable (also called target-variable), the residuals on the scale +of the dependent variable and the inner product of the estimated +parameters and the independent variables (also called covariates or +features). However, the object returned by *minpack.lm::nlsLM* +does not contain the original data set but that data set is necessary +to calculate the inner product. Hence, we make a list that +contains the model fit and the data that was used to fit the model. + +```{r} +fit_and_data <- list(fit = fit, data = d) +``` + +Now we can implement the interface + +```{r} +library(R6) +my_nls_info_extractor <- R6::R6Class( + classname = "my_nls_info_extractor", + inherit = GOF_model_info_extractor, + public = list( + yhat = function(model) { + predict(object = model$fit) + }, + y_minus_yhat = function(model) { + residuals(object = model$fit) + }, + beta_x_covariates = function(model) { + a_hat <- coef(object = model$fit) + x <- model$data$x + ret <- a_hat * x + return(ret) + } + )) +my_info_extractor <- my_nls_info_extractor$new() +``` + +Implementing *yhat* and *y_minus_yhat* is straight forward +using the function already offered by R +but *beta_x_covariates* needs special attention. The +reason is that *minpack.lm::nlsLM* can also fit very +general models of the type $m(\beta, X)$. Hence, +there is now built-in-function to extract objects +like $\beta^\top X$. Lets look at the first few data points: + +```{r} +head(d) +``` + +Now we are able to predict $y$: + +```{r} +head(my_info_extractor$yhat(model = fit_and_data)) +``` + +And calculate the difference between $y$ and our prediction: + +```{r} +head(my_info_extractor$y_minus_yhat(model = fit_and_data)) +``` + +And based on the estimated coefficient we can calculate the +inner product with $x$: + +```{r} +head(my_info_extractor$beta_x_covariates(model = fit_and_data)) +``` + +Since we did not make an assumption about the distribution of +$\epsilon$ we cannot use a parametric resampling scheme. However, +we can do a wild bootstrap that uses only the predictions +and the residuals. The class *GOF_sim_wild_rademacher* implements +this wild bootstrap but needs an info extractor to obtain the +preditions and residuals: + +```{r} +my_simulator <- GOF_sim_wild_rademacher$new( + gof_model_info_extractor = my_info_extractor +) +``` + +This class generates as many observations (according +to the fitted model) as are contained in the data set +used to fit the model. + +Again looking at first at the original data points: + +```{r} +head(d) +``` + +Now lets look at new $y$s generated according to the fitted +model, i.e. following a negative binomial distribution +subject to the independent variables: + +```{r} +head(my_simulator$resample_y(model = fit_and_data)) +``` + +Note that the resampled $y$'s sometimes equal the +observed $y$. The reason is that the this wild bootstrap +performs 'predictions +/- residual' and only the sign +is drawn at random. + +Finally, we need to implement the interface +*GOF_model_trainer* which requires a function +*refit* that is able to update the model +object by refitting it to a new data set. R already +provides the necessary function, i.e. *stats::update*. +However we combined the fitted model with the +data set in a list and we need to take into account: + +```{r} +my_nls_trainer <- R6::R6Class( + classname = "GOF_nls_trainer", + inherit = GOF_model_trainer, + public = list( + refit = function(model, data) { + fit <- update(object = model$fit, data = data) + ret <- list(fit = fit, data = data) + return(ret) + })) +my_trainer <- my_nls_trainer$new() +``` +This implementation basically equals the implementation +of *GOF\_lm/glm/\_trainer*. The only difference is that +we again store the data with the fit because *nlsLM()* +doesn't do it for us. + +Of course, fitting the model again to the original data set +results in the same fitted model. With the defined classes +we can now easily generate a new data set and refit the +model to that new data set. + +```{r} +new_data <- d +new_data$y <- my_simulator$resample_y(model = fit_and_data) +my_trainer$refit(model = fit_and_data, data = new_data)$fit +``` + +Now all ingredients are available for applying the +Goodness-of-Fit test: + +```{r} +set.seed(1) +mt <- GOF_model_test$new( + model = fit_and_data, + data = d, + nmb_boot_samples = 100, + y_name = "y", + Rn1_statistic = Rn1_CvM$new(), + gof_model_info_extractor = my_info_extractor, + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = my_simulator, + gof_model_trainer = my_trainer + ) +) +mt$get_pvalue() +``` + +# Negative Binomial using the MASS-package + +A negative binomial model is a generalized linear model. +Furthermore, within R MASS::glm.nb returns an object of class +*glm* and this package actually can process *glm*-classes. +However, MASS::glm.nb seems to have a bug that prevents +to propoerly update/refit such an object via the stats::update() +function. We briefly illustrate this using an artificial +data set: + +```{r} +library(MASS) +set.seed(1) +X1 <- rnorm(100) +X2 <- rnorm(100) +d <- data.frame( + y = MASS::rnegbin(n = 100, mu = exp(0.2 + X1 * 0.2 + X2 * 0.6), theta = 2), + x1 = X1, + x2 = X2) +fit <- MASS::glm.nb(y~x1+x2, data = d) +fit +``` + +Note that fit-object shows that the call contained the +parameter *init.theta* which obviously was not provided +by us. The problem is that this *init.theta* parameter +is used by *stats::update* during refitting resampled data. +So fitting +resampled data and fitting the original data is slightly +different from the perspective of the fitting algorithm. +To circumvent this problem we can reimplement the +corresponding interface as follows: + +```{r} +my_negbin_trainer <- R6::R6Class( + classname = "GOF_glmnb_trainer", + inherit = GOF_model_trainer, + public = list( + refit = function(model, data) { + MASS::glm.nb(formula = formula(model), data = data) + })) +``` + +This way we ensure that the original data set and +resampled data set are fitted in the same way. +Now we can create the GOF-test-class using this new refitting-class + +```{r} +set.seed(1) +mt <- GOF_model_test$new( + model = fit, + data = d, + nmb_boot_samples = 100, + y_name = "y", + Rn1_statistic = Rn1_CvM$new(), + gof_model_info_extractor = GOF_glm_info_extractor$new(), + gof_model_resample = GOF_model_resample$new( + gof_model_simulator = GOF_glm_sim_param$new(), + gof_model_trainer = my_negbin_trainer$new() + ) +) +mt$get_pvalue() +``` + +Lets compare the result with the default GOF-test for glm's + +```{r} +set.seed(1) +mt2 <- GOF_model( + model = fit, + data = d, + nmb_boot_samples = 100, + simulator_type = "parametric", + y_name = "y", + Rn1_statistic = Rn1_CvM$new() +) +mt2$get_pvalue() +``` + +In this case the p-values do not differ. However, it could be +different in other settings. diff --git a/vignettes/class_diagram.svg b/vignettes/class_diagram.svg new file mode 100644 index 0000000..b91ab2b --- /dev/null +++ b/vignettes/class_diagram.svg @@ -0,0 +1,87 @@ +Rn1_statisticdouble calc_statistic(Rn1)Rn1_KSRn1_CvMGOF_model_simulatorresample_y(model)GOF_lm_sim_paramGOF_sim_wild_rademacherGOF_glm_sim_paramGOF_model_trainerrefit(model, data)GOF_lm_trainerGOF_glm_trainerGOF_model_info_extractordouble[] yhat(model)double[] y_minus_yhat(model)double[] beta_x_covariates(model)GOF_lm_info_extractorGOF_glm_info_extractorGOF_model_resampleGOF_model_simulatorGOF_model_trainerresample()GOF_model_testGOF_model_info_exctractorGOF_model_resample_skeleton RSSRn1_statistic Rn1_statdouble[] Rn1_orgdouble[] Rn1_bootdouble[] Rn1(y_minus_yhat, order_beta_x_covariates)get_Rn1_org()get_Rn1_boot()get_pvalue() \ No newline at end of file