Nothing
# plotres.R: plot model residuals
# values for which
W1 <- 1 # model selection
W2CUM <- 2 # cumulative distribution
W3RESID <- 3 # residuals vs fitted
W4QQ <- 4 # qq plot
W5ABS <- 5 # abs residuals vs fitted
W6SQRT <- 6 # sqrt abs residuals vs fitted
W7VLOG <- 7 # abs residuals vs log fitted
W8CUBE <- 8 # cube root of the squared residuals vs log fitted
W9LOGLOG <- 9 # log abs residuals vs log fitted
# values for vs
V1FITTED <- 1 # fitted
V2INDEX <- 2 # obs number
V3RESPONSE <- 3 # response
V4LEVER <- 4 # leverages
plotres <- function(object = stop("no 'object' argument"),
which = 1:4,
info = FALSE,
versus = 1,
standardize = FALSE,
delever = FALSE,
level = 0,
id.n = 3,
labels.id = NULL,
smooth.col = 2,
grid.col = 0,
jitter = 0,
do.par = NULL,
caption = NULL,
trace = 0,
npoints = 3000,
center = TRUE,
type = NULL, # passed to predict
nresponse = NA,
object.name = quote.deparse(substitute(object)),
...) # passed to predict
{
init.global.data()
on.exit({init.global.data(); gc()}) # release memory on exit
object # make sure object exists
trace <- as.numeric(check.integer.scalar(trace, logical.ok=TRUE))
use.submodel <- dota("USE.SUBMODEL", DEF=TRUE, ...) # undoc arg (for parsnip models)
use.submodel <- is.specified(use.submodel)
# Associate the model environment with the object.
# (This is instead of passing it as an argument to plotmo's data access
# functions. It saves a few hundred references to model.env in the code.)
object.env <- get.model.env(object, object.name, trace, use.submodel)
ret <- plotmo_prolog(object, object.name, trace, ...)
object <- ret$object # the original object or a submodel (parsnip)
my.call <- ret$my.call
attr(object, ".Environment") <- object.env
if(!is.numeric(which) || !is.vector(which) || anyNA(which) ||
any(which != floor(which)) || any(which < 1) || any(which > W9LOGLOG)) {
which.err()
}
info <- check.boolean(info)
standardize <- check.boolean(standardize)
delever <- check.boolean(delever)
level <- check.level.arg(level, zero.ok=TRUE)
smooth.col <- get.smooth.col(smooth.col, ...)
grid.col <- dota("col.grid", DEF=grid.col, ...)
if(is.specified(grid.col) && is.logical(grid.col) && grid.col) # grid.col=TRUE
grid.col <- "lightgray"
check.integer.scalar(nresponse, min=1, na.ok=TRUE, logical.ok=FALSE, char.ok=TRUE)
temp <- get.plotres.data(object, object.name, which, standardize, delever,
level, versus, id.n, labels.id,
trace, npoints, type, nresponse,
...,
must.get.rsq=info || trace >= 1) # get rsq only if necessary
nresponse <- temp$nresponse # col index in the response (converted from NA if necessary)
resp.name <- temp$resp.name # used only in automatic caption, may be NULL
type <- temp$type # always a string (converted from NULL if necessary)
rinfo <- temp$rinfo # resids, scale, name, etc.
vinfo <- temp$vinfo # versus.mat, icolumns, nversus, etc.
fitted <- temp$fitted # n x 1 numeric matrix, colname is "Fitted"
which <- temp$vinfo$which # plots we don't want will have been removed
id.n <- temp$id.n # forced to zero if row indexing changed
npoints <- temp$npoints # special values have been converted
rsq <- temp$rsq # r-squared on the training data
possible.biglm.warning(object, trace)
nfigs <- length(which) * length(vinfo$icolumns)
if(nfigs == 0) {
if(trace >= 0)
warning0("plotres: nothing to plot")
return(invisible(NULL))
}
do.par <- check.do.par(do.par, nfigs) # do.par is 0, 1, or 2
# Prepare caption --- we need it now for do.par() but
# can only display it later after at least one plot.
caption <- get.caption(nfigs, do.par, caption, resp.name, type,
getCall(object), object.name, my.call)
if(do.par) {
oldpar <- par(no.readonly=TRUE)
do.par(nfigs = nfigs, caption=caption,
main1=NA, # nlines.in.main below explicitly specified below
xlab1 = dota("xlab", DEF=NULL, ...), # used only for margin spacing
ylab1 = dota("ylab", DEF=NULL, ...), # ditto
trace = trace,
nlines.in.main = # nbr of lines in main is needed for margins
nlines.in.plotres.main(object=object, which=which, versus=versus,
standardize=standardize, delever=delever, level=level, ...),
def.font.main = 1, # for compat with lm.plot
...)
if(do.par == 1)
on.exit(par(oldpar), add=TRUE)
} else { # do.par=FALSE
oldpar <- do.par.dots(..., trace=trace)
if(length(oldpar))
on.exit(do.call(par, oldpar), add=TRUE)
}
# force.auto.resids.xlim is for back compat with old versions of earth.
# To pass ylim to the w1 plot, use a w1. prefix, just like any other arg.
# So plain ylim gets passed to the residuals plot not the w1 plot.
# But for backwards compatibility when the w1 plot is
# an earth model pass plain ylim to the w1 plot unless w1.ylim is set
force.auto.resids.xlim <-
length(which) > 1 && (W1 %in% which) && inherits(object, "earth") &&
!is.dot("w1.xlim", ...)
force.auto.resids.ylim <-
length(which) > 1 && (W1 %in% which) && inherits(object, "earth") &&
!is.dot("w1.ylim", ...)
w1.retval <- list(plotted=FALSE, retval=NULL)
w3.retval <- NULL
attempted.w1.plot <- FALSE
if(any(which == W1)) {
w1.retval <- plot_w1(object=object, which=which, info=info,
standardize=standardize, delever=delever, level=level, versus=versus,
id.n=id.n, labels.id=rinfo$labs, smooth.col=smooth.col,
grid.col=grid.col, do.par=do.par,
# must do caption here if will not call plot1 later
caption=if(all(which == W1)) caption else "", trace=trace,
npoints=npoints, center=center, type=type, nresponse=nresponse,
object.name=object.name,
...)
attempted.w1.plot <- TRUE
which <- which[which != W1]
if(length(which) == 0 && !w1.retval$plotted && trace >= 0)
warning0("plotres: nothing to plot")
}
if(length(which) == 0) # nothing more to plot?
return(invisible(if(attempted.w1.plot) w1.retval$retval else w3.retval))
# we do this after the w1 call so we pass NULL to w1 if labels.id were NULL
if(is.null(rinfo$labs))
rinfo$labs <- paste(1:length(rinfo$resids))
# We plot only the residuals in iresids, but use all the
# residuals for calculating densities (where "all" actually means
# a maximum of NMAX cases, see the previous call to get.isubset).
#
# The "use.all=(nversus == V4LEVER)" keeps things easier later
# for leverage plots, but it would be nice to not have to use it.
iresids <- get.isubset(rinfo$resids, npoints, id.n,
use.all=(vinfo$nversus == V4LEVER), rinfo$scale)
xlim <- dota("xlim", DEF=NULL, ...) # TODO what is this?
for(icolumn in vinfo$icolumns) {
for(iwhich in seq_along(which)) {
if(which[iwhich] == W2CUM)
plotmo_cum(rinfo=rinfo, info=info, nfigs=nfigs, add=FALSE,
cum.col1=NA, grid.col=grid.col, jitter=0, ...)
else if(which[iwhich] == W4QQ)
plotmo_qq(rinfo=rinfo, info=info, nfigs=nfigs,
grid.col=grid.col, smooth.col=smooth.col,
id.n=id.n, iresids=iresids, npoints=npoints,
force.auto.resids.ylim=force.auto.resids.ylim,
...)
else
w3.retval <- plotresids(object=object, which=which[iwhich],
info=info, standardize=standardize, level=level,
# versus1 is what we plot along the x axis, a vector
versus1=vinfo$versus.mat[, icolumn],
id.n=id.n, smooth.col=smooth.col,
grid.col=grid.col, jitter=jitter,
npoints=npoints, center=center,
type=type,
fitted=fitted, rinfo=rinfo, rsq=rsq, iresids=iresids,
nversus=vinfo$nversus,
colname.versus1=colnames(vinfo$versus.mat)[icolumn],
force.auto.resids.xlim=force.auto.resids.xlim,
force.auto.resids.ylim=force.auto.resids.ylim,
...)
}
}
draw.caption(caption, ...)
if(trace >= 1)
printf("\ntraining rsq %.2f\n", rsq)
invisible(if(attempted.w1.plot) w1.retval$retval else w3.retval)
}
which.err <- function()
{
stop0("Bad value for which\n",
"Allowed values for which:\n",
" 1 Model\n",
" 2 Cumulative distribution\n",
" 3 Residuals vs fitted\n",
" 4 QQ plot\n",
" 5 Abs residuals vs fitted\n",
" 6 Sqrt abs residuals vs fitted\n",
" 7 Abs residuals vs log fitted\n",
" 8 Cube root of the squared residuals vs log fitted\n",
" 9 Log abs residuals vs log fitted")
}
versus.err <- function()
{
stop0("versus must be an integer or a string:\n",
" 1 fitted (default)\n",
" 2 observation numbers\n",
" 3 response\n",
" 4 leverages\n",
" \"\" predictors\n",
" \"b:\" basis functions")
}
nlines.in.plotres.main <- function(object, which, versus,
standardize, delever, level, ...)
{
w1.does.own.mar4 <- # these models do their own top margin spacing in w1 plot
inherits(object, c("gbm", "GBMFit", "glmnet", "multnet"))
auto.main.has.extra.line <- # conservative guess if main will have two lines
standardize || delever || level ||
any(which %in% W6SQRT:W9LOGLOG) ||
(versus %in% V4LEVER) || is.character(versus)
max(1 + auto.main.has.extra.line,
nlines(dota("main", ...)),
1 + if(w1.does.own.mar4) 0 else nlines(dota("w1.main", ...)))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.