R: Psi / Chi / Wgt / Rho Functions for *M-Estimation

Mpsi {robustbase} | R Documentation

## Psi / Chi / Wgt / Rho Functions for *M-Estimation

### Description

Compute Psi / Chi / Wgt / Rho functions for M-estimation, i.e., including MM, etc.

`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).

### Usage

    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))

### Arguments

`x` | numeric (“abscissa” values) vector, possibly with `attributes` such as `dim` or `names`, etc. These are preserved for the `M*()` functions (but not the `.M()` ones).
`cc` | numeric tuning constant, for some `psi` of length > 1.
`psi` | a string specifying the psi / chi / rho / wgt function; either `"huber"`, or one of the same possible specifiers as for `psi` in `lmrob.control`, i.e. currently, `"bisquare"`, `"lqq"`, `"welsh"`, `"optimal"`, `"hampel"`, or `"ggw"`.
`deriv` | an integer, specifying the order of derivative to consider; particularly, `Mpsi(x, *, deriv = -1)` is the principal function of psi(), typically denoted rho() in the literature.

### Details

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.

### Value

a numeric vector of the same length as `x`, with corresponding function (or derivative) values.

### Author(s)

Manuel Koller, notably for the original C implementation; tweaks and speedup via `.Call` and `.M*()` etc by Martin Maechler.

### References

See the vignette about “psi-Functions Available in Robustbase”.

### See Also

`psiFunc` and the `psi_func` class, both of which provide considerably more on the R side, but are less optimized for speed.

`.Mpsi.tuning.defaults`, etc, for tuning constants' defaults for`lmrob()`, and `.psi.ggw.findc()` utilities to construct such constants' vectors.

### Examples

    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))))

    ## 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)

[Package robustbase version 0.92-7 Index]