R/datagen-methods.R

Defines functions `datagen.list` `datagen.gamm` `datagen.gam` `datagen.fs.interaction` `datagen.mgcv.smooth` `datagen`

#' Generate data over the range of variables used in smooths
#'
#' For each smooth in a GAM, generate new data over the range of the variables
#' involved in a smooth.
#'
#' @param x an object for which new data is required. Currently objects of
#'   classes `"gam"`, and `"gamm"` are supported, as are smooths from **mgcv**
#'   inheriting from class `"mgcv.smooth"`.
#' @param n numeric; the number of data values to generate per term in each
#'   smooth.
#' @param data data frame; for `"mgcv.smooth"` objects, the data used to fit
#'   the GAM need to be supplied.
#' @param ... arguments passed to methods
#' @return A data frame of new values spread over the range of the
#'   observed values.
#'
#' @author Gavin L. Simpson
#'
#' @rdname datagen
#'
#' @keywords internal
`datagen` <- function(x, ...) {
    UseMethod("datagen")
}

#' @export
#' @rdname datagen
`datagen.mgcv.smooth` <- function(x, n = 100, data, ...) {
    d <- smooth_dim(x)                 # how many dimensions in smooth
    term <- smooth_terms(x)            # what term are we dealing with

    ## some smooths can't be plotted, esp n-d ones where n > 2
    if (!x$plot.me || d > 2L) {
        out <- data.frame()  # FIXME: or should we throw error/message
    }

    if (d == 1L) {                      # 1-d smooths
        xvals <- data[[term]]
        newvals <- seq_min_max(xvals, n = n)
        out <- data.frame(smooth = rep(smooth_label(x), n), x = newvals)
    } else if (d == 2L) {                            # 2-d smooths
        xvals <- data[[term[1]]]
        zvals <- data[[term[2]]]
        newx <- seq_min_max(xvals, n = n)
        newz <- seq_min_max(zvals, n = n)
        out <- expand.grid(x1 = newx, x2 = newz)
        out <- cbind(smooth = rep(smooth_label(x), n^2), out)
    } else {
        stop("Cannot handle smooths of three (3) or more terms.")
    }

    ## return
    out
}

#' @export
#' @rdname datagen
`datagen.fs.interaction` <- function(x, n = 100, data, ...) {
    d <- smooth_dim(x)                 # how many dimensions in smooth
    term <- smooth_variable(x)         # what term are we dealing with
    fterm <- smooth_factor_variable(x) # get factor associated with smooth

    ## term should be length 2, which is the smooth variable
    term <- term[term != fterm]

    ## some smooths can't be plotted, esp n-d ones where n > 2
    if (!x$plot.me || d > 2L) {
        out <- data.frame()  # FIXME: or should we throw error/message
    }

    ## get new values of continuous var
    xvals <- data[[term]]
    newx <- seq(min(xvals), max(xvals), length.out = n)

    ## get the factor var and its levels
    f <- data[[fterm]]
    fvals <- levels(f)
    nlevs <- nlevels(f)

    out <- setNames(expand.grid(x = newx, f = fvals),
                    c(term, fterm))
    out <- cbind(smooth = rep(smooth_label(x), n * nlevs), out)

    out                                 # return
}

#' @export
#' @rdname datagen
`datagen.gam` <- function(x, smooth = NULL, n = 200, ...) {
    if (is.null(smooth)) {
        stop("Argument 'smooth' must be specified and not 'NULL'.")
    }
    if (length(smooth) > 1L) {
        stop("More than one smooth requested in argument 'smooth'.")
    }
    sm <- smooths(x)
    select <- check_user_select_smooths(sm, select = smooth)
    datagen(get_smooths_by_id(x, which(select))[[1L]],
            n = n, data = x[["model"]])
}

#' @export
#' @rdname datagen
`datagen.gamm` <- function(x, ...) {
    if (!is.gamm(x)) {
        stop("Model doesn't appear to be a 'gamm()' model object.")
    }
    datagen(x[["gam"]], ...)
}

#' @export
#' @rdname datagen
`datagen.list` <- function(x, ...) {
    if (!is_gamm4(x)) {
        stop("Model doesn't appear to be a 'gamm4()' model object.")
    }
    datagen(x[["gam"]], ...)
}

Try the gratia package in your browser

Any scripts or data that you put into this service are public.

gratia documentation built on Feb. 16, 2023, 10:40 p.m.