dnt | R Documentation |
dntJKBf1
implements the summation formulas
of Johnson, Kotz and Balakrishnan (1995),
(31.15) on page 516 and (31.15') on p.519, the latter being typo-corrected
for a missing factor 1 / j!
.
dntJKBf()
is Vectorize(dntJKBf1,
c("x","df","ncp"))
, i.e., works vectorized in all three main
arguments x
, df
and ncp
.
The functions .dntJKBch1()
and .dntJKBch()
are only there
for didactical reasons allowing to check that indeed formula (31.15')
in the reference is missing a j!
factor in the denominator.
The dntJKBf*()
functions are written to also work with
arbitrary precise numbers of class
"mpfr"
(from package Rmpfr)
as arguments.
dntJKBf1(x, df, ncp, log = FALSE, M = 1000)
dntJKBf (x, df, ncp, log = FALSE, M = 1000)
## The "checking" versions, only for proving correctness of formula:
.dntJKBch1(x, df, ncp, log = FALSE, M = 1000, check=FALSE, tol.check = 1e-7)
.dntJKBch (x, df, ncp, log = FALSE, M = 1000, check=FALSE, tol.check = 1e-7)
x , df , ncp |
see R's |
log |
as in |
M |
the number of terms to be used, a positive integer. |
check |
logical indicating if checks of the formula equalities should be done. |
tol.check |
tolerance to be used for |
How to choose M
optimally has not been investigated yet and
is probably also a function of the precision of the first three arguments (see
getPrec
from Rmpfr).
Note that relatedly,
R's source code ‘R/src/nmath/dnt.c’ has claimed from 2003 till 2014
but wrongly that the noncentral t density f(x, *)
was
f(x, df, ncp) = df^(df/2) * exp(-.5*ncp^2) / (sqrt(pi)*gamma(df/2)*(df+x^2)^((df+1)/2)) * sum_{k=0}^Inf gamma((df + k + df)/2)*ncp^k / prod(1:k)*(2*x^2/(df+x^2))^(k/2) .
These functions (and this help page) prove that it was wrong.
a number for dntJKBf1()
and .dntJKBch1()
.
a numeric vector of the same length as the maximum of the lengths of
x, df, ncp
for dntJKBf()
and .dntJKBch()
.
Martin Maechler
Johnson, N.L., Kotz, S. and Balakrishnan, N. (1995) Continuous Univariate Distributions Vol~2, 2nd ed.; Wiley; chapter 31, Section 5 Distribution Function, p.514 ff
R's dt
;
(an improved version of) Viechtbauer's proposal: dtWV
.
tt <- seq(0, 10, length.out = 21)
ncp <- seq(0, 6, length.out = 31)
dt3R <- outer(tt, ncp, dt, df = 3)
dt3JKB <- outer(tt, ncp, dntJKBf, df = 3)
all.equal(dt3R, dt3JKB) # Lnx(64-b): 51 NA's in dt3R
x <- seq(-1,12, by=1/16)
fx <- dt(x, df=3, ncp=5)
re1 <- 1 - .dntJKBch(x, df=3, ncp=5) / fx ; summary(warnings()) # slow, with warnings
op <- options(warn = 2) # (=> warning == error, for now)
re2 <- 1 - dntJKBf (x, df=3, ncp=5) / fx # faster, no warnings
stopifnot(all.equal(re1[!is.na(re1)], re2[!is.na(re1)], tol=1e-6))
head( cbind(x, fx, re1, re2) , 20)
matplot(x, log10(abs(cbind(re1, re2))), type = "o", cex = 1/4)
## One of the numerical problems in "base R"'s non-central t-density:
options(warn = 0) # (factory def.)
x <- 2^seq(-12, 32, by=1/8) ; df <- 1/10
dtm <- cbind(dt(x, df=df, log=TRUE),
dt(x, df=df, ncp=df/2, log=TRUE),
dt(x, df=df, ncp=df, log=TRUE),
dt(x, df=df, ncp=df*2, log=TRUE)) #.. quite a few warnings:
summary(warnings())
matplot(x, dtm, type="l", log = "x", xaxt="n",
main = "dt(x, df=1/10, log=TRUE) central and noncentral")
sfsmisc::eaxis(1)
legend("right", legend=c("", paste0("ncp = df",c("/2","","*2"))),
lty=1:4, col=1:4, bty="n")
(doExtras <- DPQ:::doExtras()) # TRUE e.g. if interactive()
(ncp <- seq(0, 12, by = if(doExtras) 3/4 else 2))
names(ncp) <- nnMs <- paste0("ncp=", ncp)
tt <- seq(0, 5, by = 1)
dt3R <- outer(tt, ncp, dt, df = 3)
if(requireNamespace("Rmpfr")) withAutoprint({
mt <- Rmpfr::mpfr(tt , 128)
mcp <- Rmpfr::mpfr(ncp, 128)
system.time(
dt3M <- outer(mt, mcp, dntJKBf, df = 3,
M = if(doExtras) 1024 else 256)) # M=1024: 7 sec [10 sec on Winb]
relE <- Rmpfr::asNumeric(sfsmisc::relErrV(dt3M, dt3R))
relE[tt != 0, ncp != 0]
})
## all.equal(dt3R, dt3V, tol=0) # 1.2e-12
# ---- using MPFR high accuracy arithmetic (too slow for routine testing) ---
## no such kink here:
x. <- if(requireNamespace("Rmpfr")) Rmpfr::mpfr(x, 256) else x
system.time(dtJKB <- dntJKBf(x., df=df, ncp=df, log=TRUE)) # 43s, was 21s and only 7s ???
lines(x, dtJKB, col=adjustcolor(3, 1/2), lwd=3)
options(op) # reset to prev.
## Relative Difference / Approximation errors :
plot(x, 1 - dtJKB / dtm[,3], type="l", log="x")
plot(x, 1 - dtJKB / dtm[,3], type="l", log="x", xaxt="n", ylim=c(-1,1)*1e-3); sfsmisc::eaxis(1)
plot(x, 1 - dtJKB / dtm[,3], type="l", log="x", xaxt="n", ylim=c(-1,1)*1e-7); sfsmisc::eaxis(1)
plot(x, abs(1 - dtJKB / dtm[,3]), type="l", log="xy", axes=FALSE, main =
"dt(*, 1/10, 1/10, log=TRUE) relative approx. error",
sub= paste("Copyright (C) 2019 Martin Maechler --- ", R.version.string))
for(j in 1:2) sfsmisc::eaxis(j)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.