Psi / Chi / Wgt / Rho Functions for *M-Estimation
Compute Psi / Chi / Wgt / Rho functions for M-estimation, i.e., including MM, etc. For definitions and details, please use the vignette “psi-Functions Available in Robustbase”.
MrhoInf(x)
computes rho(Inf), i.e., the
normalizing or scaling constant for the transformation
from rho(.) to
rho~(.), where the latter, aka as
chi() fulfills rho~(Inf) = 1
which makes only sense for “redescending” psi functions, i.e.,
not for "huber"
.
Mwgt(x, *)
computes ψ(x)/x (fast and numerically accurately).
Mpsi(x, cc, psi, deriv = 0) Mchi(x, cc, psi, deriv = 0) Mwgt(x, cc, psi) MrhoInf(cc, psi) .Mwgt.psi1(psi, cc = .Mpsi.tuning.default(psi))
x |
numeric (“abscissa” values) vector, possibly with
|
cc |
numeric tuning constant, for some |
psi |
a string specifying the psi / chi / rho / wgt function;
either |
deriv |
an integer, specifying the order of derivative to
consider; particularly, |
Theoretically, Mchi()
would not be needed explicitly as it can be computed
from Mpsi()
and MrhoInf()
, namely, by
Mchi(x, *, deriv = d) == Mpsi(x, *, deriv = d-1) / MrhoInf(*)
for d = 0, 1, 2 (and ‘*’ containing par, psi
, and
equality is in the sense of all.equal(x,y, tol)
with a
small tol
.
Similarly, Mwgt
would not be needed strictly, as it could be
defined via Mpsi
), but the explicit definition takes care of
0/0 and typically is of a more simple form.
For experts, there are slightly even faster versions,
.Mpsi()
, .Mwgt()
, etc.
.Mwgt.psi1()
mainly a utility for nlrob()
,
returns a function
with similar semantics as
psi.hampel
, psi.huber
, or
psi.bisquare
from package MASS. Namely,
a function with arguments (x, deriv=0)
, which for
deriv=0
computes Mwgt(x, cc, psi)
and otherwise computes
Mpsi(x, cc, psi, deriv=deriv)
.
.Mpsi()
, .Mchi()
, .Mwgt()
, and .MrhoInf()
are
low-level versions of
Mpsi()
, Mchi()
, Mwgt()
, and MrhoInf()
, respectively,
and .psi2ipsi()
provides the psi-function integer codes needed
for ipsi
argument of the .M*()
functions.
For psi = "ggw"
, the rho() function has no closed
form and must be computed via numerical integration, apart from 6
special cases including the defaults, see the ‘Details’ in
help(.psi.ggw.findc)
.
a numeric vector of the same length as x
, with corresponding
function (or derivative) values.
Manuel Koller, notably for the original C implementation;
tweaks and speedup via .Call
and .M*()
etc by
Martin Maechler.
See the vignette about “psi-Functions Available in Robustbase”.
.Mpsi.tuning.defaults
, etc, for tuning constants'
defaults forlmrob()
, and .psi.ggw.findc()
utilities to construct such constants' vectors.
x <- seq(-5,7, by=1/8) matplot(x, cbind(Mpsi(x, 4, "biweight"), Mchi(x, 4, "biweight"), Mwgt(x, 4, "biweight")), type = "l") abline(h=0, v=0, lty=2, col=adjustcolor("gray", 0.6)) hampelPsi (ccHa <- hampelPsi @ xtras $ tuningP $ k) psHa <- hampelPsi@psi(x) ## using Mpsi(): Mp.Ha <- Mpsi(x, cc = ccHa, psi = "hampel") stopifnot(all.equal(Mp.Ha, psHa, tolerance = 1e-15)) psi.huber <- .Mwgt.psi1("huber") if(getRversion() >= "3.0.0") stopifnot(identical(psi.huber, .Mwgt.psi1("huber", 1.345), ignore.env=TRUE)) curve(psi.huber(x), -3, 5, col=2, ylim = 0:1) curve(psi.huber(x, deriv=1), add=TRUE, col=3) ## and show that this is indeed the same as MASS::psi.huber() : x <- runif(256, -2,3) stopifnot(all.equal(psi.huber(x), MASS::psi.huber(x)), all.equal( psi.huber(x, deriv=1), as.numeric(MASS::psi.huber(x, deriv=1)))) ## and how to get MASS::psi.hampel(): psi.hampel <- .Mwgt.psi1("Hampel", c(2,4,8)) x <- runif(256, -4, 10) stopifnot(all.equal(psi.hampel(x), MASS::psi.hampel(x)), all.equal( psi.hampel(x, deriv=1), as.numeric(MASS::psi.hampel(x, deriv=1)))) ## "lqq" / "LQQ" and its tuning constants: ctl0 <- lmrob.control(psi = "lqq", tuning.psi=c(-0.5, 1.5, 0.95, NA)) ctl <- lmrob.control(psi = "lqq", tuning.psi=c(-0.5, 1.5, 0.90, NA)) ctl0$tuning.psi ## keeps the vector _and_ has "constants" attribute: ## [1] -0.50 1.50 0.95 NA ## attr(,"constants") ## [1] 1.4734061 0.9822707 1.5000000 ctl$tuning.psi ## ditto: ## [1] -0.5 1.5 0.9 NA \ .."constants" 1.213726 0.809151 1.500000 stopifnot(all.equal(Mpsi(0:2, cc = ctl$tuning.psi, psi = ctl$psi), c(0, 0.977493, 1.1237), tol = 6e-6)) x <- seq(-4,8, by = 1/16) ## Show how you can use .Mpsi() equivalently to Mpsi() stopifnot(all.equal( Mpsi(x, cc = ctl$tuning.psi, psi = ctl$psi), .Mpsi(x, ccc = attr(ctl$tuning.psi, "constants"), ipsi = .psi2ipsi("lqq")))) stopifnot(all.equal( Mpsi(x, cc = ctl0$tuning.psi, psi = ctl0$psi, deriv=1), .Mpsi(x, ccc = attr(ctl0$tuning.psi, "constants"), ipsi = .psi2ipsi("lqq"), deriv=1))) ## M*() preserving attributes : x <- matrix(x, 32, 8, dimnames=list(paste0("r",1:32), col=letters[1:8])) comment(x) <- "a vector which is a matrix" px <- Mpsi(x, cc = ccHa, psi = "hampel") stopifnot(identical(attributes(x), attributes(px))) ## The "optimal" psi exists in two versions "in the litterature": --- ## Maronna et al. 2006, 5.9.1, p.144f: psi.M2006 <- function(x, c = 0.013) sign(x) * pmax(0, abs(x) - c/dnorm(abs(x))) ## and the other is the one in robustbase from 'robust': via Mpsi(.., "optimal") ## Here are both for 95% efficiency: (c106 <- .Mpsi.tuning.default("optimal")) c1 <- curve(Mpsi(x, cc = c106, psi="optimal"), -5, 7, n=1001) c2 <- curve(psi.M2006(x), add=TRUE, n=1001, col=adjustcolor(2,0.4), lwd=2) abline(0,1, v=0, h=0, lty=3) ## the two psi's are similar, but really quite different ## a zoom into Maronna et al's: c3 <- curve(psi.M2006(x), -.5, 1, n=1001); abline(h=0,v=0, lty=3);abline(0,1, lty=2)
Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.