Nothing
#' @title
#' The Asselin de Beauville mode estimator
#'
#' @description
#' This mode estimator is based on the algorithm
#' described in Asselin de Beauville (1978).
#'
#' @note
#' The user may call \code{asselin} through
#' \code{mlv(x, method = "asselin", ...)}.
#'
#' @references
#' \itemize{
#' \item Asselin de Beauville J.-P. (1978).
#' Estimation non parametrique de la densite et du mode,
#' exemple de la distribution Gamma.
#' \emph{Revue de Statistique Appliquee}, \bold{26}(3):47-70.
#' }
#'
#' @param x
#' numeric. Vector of observations.
#'
#' @param bw
#' numeric. A number in \code{(0, 1]}.
#' If \code{bw = 1}, the selected 'modal chain' may be too long.
#'
#' @param ...
#' further arguments to be passed to the \code{\link[stats]{quantile}} function.
#'
#' @return
#' A numeric value is returned, the mode estimate.
#'
#' @seealso
#' \code{\link[modeest]{mlv}} for general mode estimation.
#'
#' @importFrom stats median quantile
#' @export
#' @aliases Asselin
#'
#' @examples
#' x <- rbeta(1000, shape1 = 2, shape2 = 5)
#'
#' ## True mode:
#' betaMode(shape1 = 2, shape2 = 5)
#'
#' ## Estimation:
#' asselin(x, bw = 1)
#' asselin(x, bw = 1/2)
#' mlv(x, method = "asselin")
#'
asselin <-
function(x,
bw = NULL, # bw = 1 donne une chaine modale longue, bw < 1 est plus severe
...)
{
# TODO: look at 'na.contiguous'
if (is.null(bw)) bw <- 1
nx <- length(x)
kmax <- floor(ifelse(nx < 30, 10, 15)*log(nx))
y <- sort(x)
ok1 <- FALSE
while (!ok1) {
ny <- length(y)
if (ny==1) return(y)
qy <- stats::quantile(y, probs = c(0.1, 0.25, 0.5, 0.75, 0.9),
names = FALSE, ...)
delta <- min(qy[5] - qy[4], qy[2] - qy[1])
a <- qy[1] - 3*delta
b <- qy[5] + 3*delta
yab <- y[y>=a & y <= b]
k <- kmax
ok2 <- FALSE
while (!ok2) {
#hy <- hist(yab, breaks = k, plot = FALSE);b <- hy$breaks;n <- c(hy$counts, 0)
b <- seq(from = min(yab), to = max(yab), length = k+1)
n <- c(tabulate(findInterval(yab, b[-(k+1)])), 0)
N <- sum(n)
v <- as.numeric(n >= N/k)
## Beginning of the first chain
w <- which.max(v)
v2 <- v[w:(k + 1)]
## End of the first chain
w2 <- which.min(v2) + w - 1
v3 <- v[w2:(k + 1)]
## Length of the first chain
nc <- sum(n[w:(w2 - 1)])
## There exists another chain, and the first chain has only one element
if (any(v3 == 1) && nc == 1) {
if (k > 3) {
k <- k-1
} else if (k == 3) {
if (n[3] > 1) {
w <- 3
w2 <- 4
}
ok2 <- TRUE
} else {
stop("k < 3", call. = FALSE)
}
## There exists another chain, and the first chain has more than one element
} else if (any(v3 == 1) && nc > 1) {
if (k > 3) {
k <- k-1
### In this case, w = 1 necessarily
} else if (k == 3) {
if (n[3] > 1) {
p1 <- (1/n[1])*prod(diff(yab[yab >= b[w] & yab <= b[w2]])) # here, n[1] = length(first chain)
p2 <- (1/n[3])*prod(diff(yab[yab >= b[3] & yab <= b[4]])) # and n[3] = length(second chain)
if (p1 > p2) {
w <- 3
w2 <- 4
}
}
ok2 <- TRUE
} else {
stop("k < 3", call. = FALSE)
}
## There is no other chain: the modal chain is found!
} else if (!any(v3 == 1)) {
ok2 <- TRUE
}
}
## Update 'nc'
nc <- sum(n[w:(w2-1)])
#cat("Modal chain length = ", nc, "\n")
d <- abs((qy[4] + qy[2] - 2*qy[3])/(qy[4] - qy[2]))
nc2 <- ny*(1-d)
#cat("d = ", d, "\n")
y <- yab[yab >= b[w] & yab <= b[w2]]
if (nc == ny) {
ok1 <- TRUE
} else if (nc <= ifelse(nx < 30, nx/3, bw*nc2)) {
ok1 <- TRUE
} else {
ok1 <- FALSE
}
}
stats::median(y)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.