File: select_parameters.R

package info (click to toggle)
r-cran-parameters 0.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,044 kB
  • sloc: sh: 15; makefile: 2
file content (130 lines) | stat: -rw-r--r-- 4,282 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#' Automated selection of model parameters
#'
#' This function performs an automated selection of the 'best' parameters, updating and returning the "best" model.
#'
#' @param model A statistical model (of class \code{lm}, \code{glm}, \code{merMod}, \code{stanreg} or \code{brmsfit}).
#' @param ... Arguments passed to or from other methods.
#'
#' @details
#'   \subsection{Classical lm and glm}{
#'     For frequentist GLMs, \code{select_parameters()} performs an AIC-based
#'     stepwise selection.
#'   }
#'   \subsection{Mixed models}{
#'     For mixed models of class \code{merMod}, stepwise selection is
#'     based on \code{\link[cAIC4:stepcAIC]{stepcAIC()}}. This step function
#'     only searches the "best" model based on the random effects structure,
#'     i.e. \code{select_parameters()} adds or excludes random effects until
#'     the cAIC can't be improved further.
#'   }
#'   \subsection{Bayesian models}{
#'     For Bayesian models, it uses the \pkg{projpred} package.
#'   }
#'
#' @examples
#' model <- lm(mpg ~ ., data = mtcars)
#' select_parameters(model)
#'
#' model <- lm(mpg ~ cyl * disp * hp * wt, data = mtcars)
#' select_parameters(model)
#' \donttest{
#' # lme4 -------------------------------------------
#' if (require("lme4")) {
#'   model <- lmer(
#'     Sepal.Width ~ Sepal.Length * Petal.Width * Petal.Length + (1 | Species),
#'     data = iris
#'   )
#'   select_parameters(model)
#' }
#' }
#'
#' \dontrun{
#' # rstanarm -------------------------------------------
#' if (require("rstanarm") && require("projpred")) {
#'   model <- stan_glm(
#'     mpg ~ .,
#'     data = mtcars,
#'     iter = 500, refresh = 0, verbose = FALSE
#'   )
#'   select_parameters(model, cross_validation = TRUE)
#'
#'   model <- stan_glm(
#'     mpg ~ cyl * disp * hp,
#'     data = mtcars,
#'     iter = 500, refresh = 0, verbose = FALSE
#'   )
#'   select_parameters(model, cross_validation = FALSE)
#' }}
#'
#' @return The model refitted with optimal number of parameters.
#' @export
select_parameters <- function(model, ...) {
  UseMethod("select_parameters")
}


#' @rdname select_parameters
#' @inheritParams stats::step
#' @importFrom stats step
#' @export
select_parameters.lm <- function(model, direction = "both", steps = 1000, k = 2, ...) {
  junk <- utils::capture.output(best <- stats::step(model,
    trace = 0,
    direction = direction,
    steps = steps,
    k = k,
    ...
  ))

  best
}



#' @importFrom insight find_random
#' @rdname select_parameters
#' @export
select_parameters.merMod <- function(model, direction = "backward", steps = 1000, ...) {

  # Using cAIC4's stepcAIC()
  if (!requireNamespace("cAIC4", quietly = TRUE)) {
    stop("Package 'cAIC4' required for this function to work. Please install it by running `install.packages('cAIC4')`.")
  }

  # Find slope and group candidates
  # data <- insight::get_data(model)
  # factors <- names(data[sapply(data, is.factor)])
  # if(length(factors) == 0){
  #   factors <- NULL
  # }
  # nums <- names(data[sapply(data, is.numeric)])
  # if(length(nums) == 0){
  #   nums <- NULL
  # }

  factors <- unique(c(
    insight::find_random(model, split_nested = FALSE, flatten = TRUE),
    insight::find_random(model, split_nested = TRUE, flatten = TRUE)
  ))
  factors <- gsub(":", "/", factors, fixed = TRUE)


  best <- suppressMessages(suppressWarnings(cAIC4::stepcAIC(model,
    # slopeCandidates = nums,
    groupCandidates = factors,
    direction = direction,
    steps = steps,
    allowUseAcross = TRUE
  )$finalModel))


  # Using MuMIn's dredge(): works nicely BUT throws unnecessary warnings and requires to set global options for na.action even tho no NaNs.
  # The code is here: https://github.com/cran/MuMIn/blob/master/R/dredge.R Maybe it could be reimplemented?
  # if (!requireNamespace("MuMIn", quietly = TRUE)) {
  #   stop("Package 'MuMIn' required for this function to work. Please install it by running `install.packages('MuMIn')`.")
  # }
  # model <- lmer(Sepal.Width ~ Sepal.Length * Petal.Width * Petal.Length + (1 | Species), data = iris, na.action = na.fail)
  # summary(MuMIn::get.models(MuMIn::dredge(model), 1)[[1]])

  best
}