qnormR {DPQ} | R Documentation |
Pure R version of R's qnorm()
with Diagnostics and Tuning Parameters
Description
Computes R level implementations of R's qnorm()
as
implemented in C code (in R's ‘Rmathlib’), historically and present.
Usage
qnormR1(p, mu = 0, sd = 1, lower.tail = TRUE, log.p = FALSE, trace = 0, version = )
qnormR (p, mu = 0, sd = 1, lower.tail = TRUE, log.p = FALSE, trace = 0,
version = c("4.0.x", "1.0.x", "1.0_noN", "2020-10-17", "2022-08-04"))
Arguments
p |
probability |
mu |
mean of the normal distribution. |
sd |
standard deviation of the normal distribution. |
lower.tail , log.p |
logical, see, e.g., |
trace |
logical or integer; if positive or |
version |
a |
Details
For qnormR1(p, ..)
, p
must be of length one, whereas
qnormR(p, m, s, ..)
works vectorized in p
, mu
, and
sd
. In the DPQ package source, qnormR
is simply the result of
Vectorize(qnormR1, ...)
.
Value
a numeric vector like the input q
.
Author(s)
Martin Maechler
References
For version
s "1.0.x"
and "1.0_noN"
:
Beasley, J.D. and Springer, S.G. (1977)
Algorithm AS 111: The Percentage Points of the Normal Distribution.
JRSS C (Appied Statistics) 26, 118–121; doi:10.2307/2346889.
For the asymptotic approximations used in version
s newer than
"4.0.x"
, i.e., "2020-10-17"
and later, see the
reference(s) on qnormAsymp
's help page.
See Also
Examples
qR <- curve(qnormR, n = 2^11)
abline(h=0, v=0:1, lty=3, col=adjustcolor(1, 1/2))
with(qR, all.equal(y, qnorm(x), tol=0)) # currently shows TRUE
with(qR, all.equal(pnorm(y), x, tol=0)) # currently: mean rel. diff.: 2e-16
stopifnot(with(qR, all.equal(pnorm(y), x, tol = 1e-14)))
(ver.qn <- eval(formals(qnormR)$version)) # the possible versions
(doExtras <- DPQ:::doExtras()) # TRUE e.g. if interactive()
lp <- - 4^(1:30) # effect of 'trace = *' :
qpAll <- sapply(ver.qn, function (V)
qnormR(lp, log.p=TRUE, trace=doExtras, version = V))
head(qpAll) # the "1.0" versions underflow quickly ..
cAdj <- adjustcolor(palette(), 1/2)
matplot(-lp, -qpAll, log="xy", type="l", lwd=3, col=cAdj, axes=FALSE,
main = "- qnormR(lp, log.p=TRUE, version = * )")
sfsmisc::eaxis(1, nintLog=15, sub=2); sfsmisc::eaxis(2)
lines(-lp, sqrt(-2*lp), col=cAdj[ncol(qpAll)+1])
leg <- as.expression(c(paste("version=", ver.qn), quote(sqrt(-2 %.% lp))))
matlines(-lp, -qpAll[,2:3], lwd=6, col=cAdj[2:3])
legend("top", leg, bty='n', col=cAdj, lty=1:3, lwd=2)
## Showing why/where R's qnorm() was poor up to 2020: log.p=TRUE extreme tail
##% MM: more TODO? --> ~/R/MM/NUMERICS/dpq-functions/qnorm-extreme-bad.R
qs <- 2^seq(0, 155, by=1/8)
lp <- pnorm(qs, lower.tail=FALSE, log.p=TRUE)
## The inverse of pnorm() fails BADLY for extreme tails:
## this is identical to qnorm(..) in R <= 4.0.x:
qp <- qnormR(lp, lower.tail=FALSE, log.p=TRUE, version="4.0.x")
## asymptotically correct approximation :
qpA <- sqrt(- 2* lp)
##^
col2 <- c("black", adjustcolor(2, 0.6))
col3 <- c(col2, adjustcolor(4, 0.6))
## instead of going toward infinity, it converges at 9.834030e+07 :
matplot(-lp, cbind(qs, qp, qpA), type="l", log="xy", lwd = c(1,1,3), col=col3,
main = "Poorness of qnorm(lp, lower.tail=FALSE, log.p=TRUE)",
ylab = "qnorm(lp, ..)", axes=FALSE)
sfsmisc::eaxis(1); sfsmisc::eaxis(2)
legend("top", c("truth", "qnorm(.) = qnormR(., \"4.0.x\")", "asymp. approx"),
lwd=c(1,1,3), lty=1:3, col=col3, bty="n")
rM <- cbind(lp, qs, 1 - cbind(relE.qnorm=qp, relE.approx=qpA)/qs)
rM[ which(1:nrow(rM) %% 20 == 1) ,]