File: grenander.R

package info (click to toggle)
r-cran-modeest 2.4.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 280 kB
  • sloc: makefile: 2
file content (140 lines) | stat: -rw-r--r-- 4,125 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#' @title 
#' The Grenander mode estimator
#' 
#' @description 
#' This function computes the Grenander mode estimator.
#' 
#' @details 
#' The Grenander estimate is defined by 
#' \deqn{ \frac{ \sum_{j=1}^{n-k} \frac{(x_{j+k} + x_{j})}{2(x_{j+k} - x_{j})^p} }
#' { \sum_{j=1}^{n-k} \frac{1}{(x_{j+k} - x_{j})^p} } }{ ( sum_{j=1}^{n-k} (x_{j+k} + x_{j})/(2(x_{j+k} - x_{j})^p) ) / ( sum_{j=1}^{n-k} 1/((x_{j+k} - x_{j})^p) ) } 
#' 
#' If \eqn{p}{p} tends to infinity, this estimate tends to the Venter mode estimate; 
#' this justifies to call \code{\link[modeest]{venter}} if \code{p = Inf}. 
#' 
#' The user should either give the bandwidth \code{bw} or the argument \code{k}, 
#' \code{k} being taken equal to \code{ceiling(bw*n) - 1} if missing.
#' 
#' @references 
#' \itemize{
#'   \item Grenander U. (1965). 
#'   Some direct estimates of the mode. 
#'   \emph{Ann. Math. Statist.}, \bold{36}:131-138.
#'   
#'   \item Dalenius T. (1965). 
#'   The Mode - A Negleted Statistical Parameter. 
#'   \emph{J. Royal Statist. Soc. A}, \emph{128}:110-117. 
#'   
#'   \item Adriano K.N., Gentle J.E. and Sposito V.A. (1977). 
#'   On the asymptotic bias of Grenander's mode estimator. 
#'   \emph{Commun. Statist.-Theor. Meth. A}, \bold{6}:773-776. 
#'   
#'   \item Hall P. (1982). 
#'   Asymptotic Theory of Grenander's Mode Estimator. 
#'   \emph{Z. Wahrsch. Verw. Gebiete}, \bold{60}:315-334.
#' }
#' 
#' @note 
#' The user may call \code{grenander} through 
#' \code{mlv(x, method = "grenander", bw, k, p, ...)}. 
#'
#' @param x 
#' numeric. Vector of observations.
#' 
#' @param bw
#' numeric. The bandwidth to be used. Should belong to (0, 1].
#' 
#' @param k
#' numeric. Paramater 'k' in Grenander's mode estimate, see below. 
#' 
#' @param p
#' numeric. Paramater 'p' in Grenander's mode estimate, see below. 
#' If \code{p = Inf}, the function \code{\link[modeest]{venter}} is used. 
#' 
#' @param ...
#' Additional arguments to be passed to \code{\link[modeest]{venter}}. 
#' 
#' @return 
#' A numeric value is returned, the mode estimate. 
#' If \code{p = Inf}, the \code{\link[modeest]{venter}} mode estimator is returned. 
#' 
#' @author D.R. Bickel for the original code, 
#' P. Poncet for the slight modifications introduced.
#' 
#' @seealso 
#' \code{\link[modeest]{mlv}} for general mode estimation; 
#' \code{\link[modeest]{venter}} for the Venter mode estimate. 
#' 
#' @export
#' @aliases Grenander
#' 
#' @examples 
#' # Unimodal distribution
#' x <- rnorm(1000, mean = 23, sd = 0.5) 
#' 
#' ## True mode
#' normMode(mean = 23, sd = 0.5) # (!)
#' 
#' ## Parameter 'k'
#' k <- 5
#' 
#' ## Many values of parameter 'p'
#' ps <- seq(0.1, 4, 0.01)
#' 
#' ## Estimate of the mode with these parameters
#' M <- sapply(ps, function(p) grenander(x, p = p, k = k))
#' 
#' ## Distribution obtained
#' plot(density(M), xlim = c(22.5, 23.5))
#'
grenander <-
function(x, 
         bw = NULL,
         k,
         p,
         ...)
{
  if (p == Inf) {
    message("argument 'p' is infinite. Venter's mode estimator is used")
    return(venter(x = x, bw = bw, k = k, ...)) 
  }

  ny <- length(x)    

  if (missing(k) && !is.null(bw)) {
    if (bw <= 0 || bw > 1) {
      stop("argument 'bw' must belong to (0, 1]", 
           call. = FALSE)
    }
    k <- ceiling(bw*ny) - 1
  } else if (missing(k) && is.null(bw)) {
    k <- ceiling(ny/2) - 1
  }
  
  if (k < 0 || k >= ny) {
    stop("argument 'k' must belong to [0, length('x'))", 
         call. = FALSE)
  }

  y <- sort(x)

  inf <- y[1:(ny-k)]
  sup <- y[(k+1):ny]
  diff <- sup - inf
  tot <- inf + sup
  if (any(diff==0)) {
    warning("limiting value of Grenander mode used", 
            call. = FALSE) # TODO: be more specific
    M <- mean(ifelse(diff==0, tot, NA), na.rm = TRUE)/2
  } else {
    b <- sum(tot/diff^p)/2
    a <- sum(1/diff^p)
    if (is.finite(b/a)) {
      M <- b/a
    } else {
      stop("function 'grenander' failed. Argument 'p' may be too large", 
           call. = FALSE)
    }
  }
  M
}