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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
|
#### This is from the R package
####
#### rrcov : Scalable Robust Estimators with High Breakdown Point
####
#### by Valentin Todorov
### This program is free software; you can redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation; either version 2 of the License, or
### (at your option) any later version.
###
### This program is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with this program; if not, a copy is available at
### http://www.r-project.org/Licenses/
plot.lts <- function(x,
which = c("all", "rqq","rindex", "rfit", "rdiag"),
classic = FALSE,
ask = (which[1] == "all" && dev.interactive()),
id.n, ...) {
if (!inherits(x, "lts"))
stop("Use only with 'lts' objects")
ltsPlot(x, which, classic, ask, id.n, ...)
}
ltsPlot <- function(x,
which = c("all", "rqq","rindex", "rfit", "rdiag"),
classic = FALSE,
ask = FALSE,
id.n, ...)
{
##@bdescr
## Make plots for model checking and outlier detection based on
## the LTS regression estimates:
## rqq - normal quantile plot of the LTS and LS residuals
## rindex - standardized LTS/LS Residuals versus index
## rfit - standardized LTS/LS Residuals versus fitted values
## rdiag - regression diagnostic plot
##
##@edescr
##
##@in x : [object] An lts object
##@in which : [character] A plot option, one of:
## rqq:
## rdiag:
## rfit:
## rindex:
## default is "rqq"
##@in classic : [logical] If true the classical plot will be displayed too
## default is classic=FALSE
##@in id.n : [number] number of observations to be identified with a label.
label <- function(x, y, ord, lab, id.n, ...)
{
if(id.n) {
n <- length(y)
which <- order(ord)[(n - id.n + 1):n]
lab <- if(missing(lab)) which else lab[which]
## how to adjust the labels?
## a) adj=0.1
## b) x=x+xrange
## c) pos=4 (to the left of the observation)
## d) additionaly to pos specify offset=0.2 (fraction of a character)
xrange <- par("usr")
xrange <- (xrange[2] - xrange[1])/50
text(x[which], y[which], pos = 4, offset = 0.2, lab, ...)
}
}
## The R function 'qqline' (package::stats) adds a line to a
## normal quantile-quantile plot which passes through the
## first and third quartiles. In S this function returns the
## slope and intercept of the line, but not in R.
## Here we need the slope and intercept in order to sort the
## residuals according to their distance from the line.
myqqline <- function(y, datax = FALSE, ...) {
y <- quantile(y[!is.na(y)],c(0.25, 0.75))
x <- qnorm(c(0.25, 0.75))
if(datax) {
slope <- diff(x)/diff(y)
int <- x[1] - slope*y[1]
} else {
slope <- diff(y)/diff(x)
int <- y[1]-slope*x[1]
}
abline(int, slope, ...)
invisible(list(int = int, slope = slope))
}
myqqplot <- function(r, classic = FALSE, lab, id.n, ...) {
## Normal QQ-plot of residuals:
## Produces a Quantile-Quantile plot in which the vector r is plotted
## against the quantiles of a standard normal distribution.
xlab <- "Quantiles of the standard normal distribution"
ylab <- if(classic)
"Standardized LS residual"
else "Standardized LTS residual"
qq <- qqnorm(r, mgp = mgp, xlab = xlab, ylab = ylab, ...)
ll <- myqqline(r, lty = 2, ...)
ord <- abs(qq$y - ll$int - ll$slope * qq$x)
label(qq$x, qq$y, ord, lab, id.n, ...)
}
indexplot <- function(r, scale, classic = FALSE, lab, id.n, ...) {
## Index plot of standardized residuals:
## Plot the vector r (LTS or LS residuals) against
## the observation indexes. Identify by a label the id.n
## observations with largest value of r.
## Use classic=FALSE/TRUE to choose the label of the vertical axes
## VT:: 26.12.2004
if(scale == 0)
stop("Index plot of standardized residuals is not avalable if scale = 0")
xlab <- "Index"
ylab <-
if(classic)
"Standardized LS residual"
else "Standardized LTS residual"
x <- 1:length(r)
y <- r/scale
ylim <- c(min(-3, min(y)), max(3, max(y)))
plot(x, y, ylim = ylim, mgp = mgp, xlab = xlab, ylab = ylab, ...)
label(x, y, ord = abs(y), lab, id.n, ...)
abline(h = 0, lty = 4, ...)
abline(h = c(-2.5, 2.5), ...)
mtext(c("-2.5","2.5"), side = 4, line = 1.2, at = c(-2.5, 2.5), ...)
title(main = "Residuals vs Index")
}
##' Tukey-Anscombe Plot (rename ?!)
fitplot <- function(obj, classic = FALSE, lab, id.n, ...) {
## Standardized residuals vs Fitted values plot:
## Plot the vector r (LTS or LS residuals) against
## the corresponding fitted values. Identify by a
## label the id.n observations with largest value of r.
## Use classic=FALSE/TRUE to choose the label of the vertical axes
## VT:: 26.12.2004
if(obj$scale == 0)
stop("Standardized residuals vs Fitted values plot is not avalable if scale = 0")
## x <- obj$X %*% as.matrix(obj$coef)
x <- obj$fitted.values
y <- obj$residuals/obj$scale
ylim <- c(min(-3, min(y)), max(3, max(y)))
yname <- names(obj$scale)
xlab <- paste("Fitted :", yname)
ylab <- if(classic)
"Standardized LS residual"
else "Standardized LTS residual"
plot(x, y, ylim = ylim, mgp = mgp, xlab = xlab, ylab = ylab, ...)
label(x, y, ord = abs(y), lab, id.n, ...)
abline(h = 0, lty = 4, ...)
abline(h = c(-2.5, 2.5), ...)
mtext(c("-2.5","2.5"), side = 4, line = 1.2, at = c(-2.5, 2.5), ...)
title(main = "Residuals vs Fitted")
} ## fitplot()
rdiag <- function(obj, classic = FALSE, lab, id.n, ...) {
## Regression diagnostic plot:
## Plot the vector of the standardized residuals against
## the robust distances of the predictor variables
## Identify by a label the id.n observations with largest value of r.
## Use classic=FALSE/TRUE to choose the label of the vertical axes
p <- if(obj$intercept) length(obj$coef) - 1 else length(obj$coef)
if(p <= 0)
warning("Diagnostic plot is not available for univar\niate location and scale estimation")
## VT:: 26.12.2004
if(obj$scale <= 0)
stop("Regression Diagnostic plot is not avalable if scale = 0")
if(is.null(obj$RD))
stop("Regression Diagnostic plot is not avalable: option mcd=F was set in ltsReg().")
if(obj$RD[1] == "singularity")
stop("The MCD covariance matrix was singular.")
if(classic) {
xlab <- "Mahalanobis distance"
ylab <- "Standardized LS residual"
} else {
xlab <- "Robust distance computed by MCD"
ylab <- "Standardized LTS residual"
}
## VT:: 18.01.20045
## set id.n to the number of all outliers:
## regression outliers (weight==0)+ leverage points (RD > cutoff)
if(missing(id.n)) {
id.n <- length(unique(c(which(obj$RD > sqrt(qchisq(0.975, p))),
which(obj$lts.wt == 0))))
}
quant <- max(c(sqrt(qchisq(0.975, p)), 2.5))
x <- obj$RD
y <- obj$residuals/obj$scale
## xlim <- c(0, max(quant + 0.1, max(x)))
ylim <- c(min(-3, min(y)), max(3, max(y)))
plot(x, y, ylim = ylim, mgp = mgp, xlab = xlab, ylab = ylab,
main = "Regression Diagnostic Plot", ...)
ord <- apply(abs(cbind(x/2.5, y/quant)), 1, max)
label(x, y, ord = ord, lab, id.n, ...)
abline(v = quant, h = c(-2.5, 2.5), ...)
mtext(c("-2.5","2.5"), side = 4, line = 1.2, at = c(-2.5, 2.5), ...)
} ## rdiag()
## parameters and preconditions
which <- match.arg(which)
r <- residuals(x)
n <- length(r)
id.n.missing <- missing(id.n) || is.null(id.n)
## if id.n is missing, it will be set to a default for each plot.
if(!id.n.missing) {
id.n <- as.integer(id.n)
if(id.n < 0 || id.n > n)
stop("'id.n' must be in {1,..,",n,"}")
}
mgp <- c(2.5, 1, 0) # set the margin line (in 'mex' units) for the:
## - axis title,
## - axis labels and
## - axis line.
## The default is 'c(3, 1, 0)'.
if(!classic)
par(pty = "m")
else {
opar <- par(mfrow = c(1,2), pty = "m")
on.exit(par(opar))
## calculate the LS regression (using LTS with alpha = 1)
## if intercept, obj$X is augmented with a column of 1s - remove it
if(x$intercept && # model with intercept
length(dim(x$X)) == 2 && # X is 2-dimensional
(nc <- ncol(x$X)) > 1 && # X has more than 1 column
all(x$X[,1] == 1)) # the first column of X is all 1s
X <- x$X[, -1]
else
X <- x$X
obj.cl <- ltsReg(X, x$Y, intercept = x$intercept, alpha = 1)
}
if (ask) {
op <- par(ask = TRUE)
on.exit(par(op))
}
## set id.n to the number of regression outliers (weight==0):
nx <- if(id.n.missing) length(which(x$lts.wt == 0)) else id.n
if(which == "all" || which == "rqq") {
## VT::20.12.2006 - the standardized residuals are in x$resid
## - no change for the other plot functions - the residuals will be standardized
## inside indexplot(), fitplot(), etc
myqqplot(x$resid, id.n = nx, ...) # normal QQ-plot of the LTS residuals
if(classic) # normal QQ-plot of the LS residuals
myqqplot(obj.cl$resid, classic = TRUE, id.n = nx, ...)
}
if(which == "all" || which == "rindex") {
indexplot(x$residuals, x$scale, id.n = nx, ...) # index plot of the LTS residuals
if(classic) # index plot of the LS residuals
indexplot(obj.cl$residuals, obj.cl$scale, classic = TRUE, id.n = nx, ...)
}
if(which == "all" || which == "rfit") {
fitplot(x, id.n = nx, ...)
if(classic)
fitplot(obj.cl, classic = TRUE, id.n = nx, ...)
}
if(which == "all" || which == "rdiag") {
rdiag(x, id.n = id.n, ...)
if(classic)
rdiag(obj.cl, classic = TRUE, id.n = id.n, ...)
}
}
|