【问题标题】:Explain the quantile() function in R解释 R 中的 quantile() 函数
【发布时间】:2010-09-10 20:02:24
【问题描述】:

我整天都对 R 分位数函数感到困惑。

我对分位数的工作原理有一个直观的概念,并且拥有硕士学位。在统计数据中,但天哪,天哪,它的文档让我感到困惑。

来自文档:

Q[i](p) = (1 - 伽马) x[j] + 伽马 x[j+1],

到目前为止,我已经同意了。对于类型 i 分位数,它是 x[j] 和 x[j+1] 之间的插值,基于一些神秘的常数 gamma

其中 1

那么,如何计算j?米?

对于连续样本分位数 类型(4到9),样本 分位数可以通过线性获得 k阶之间的插值 统计和 p(k):

p(k) = (k - alpha) / (n - alpha - beta + 1), 其中 α 和 β 是确定的常数 按类型。此外,m = alpha + p(1 - alpha - beta),而 gamma = g。

现在我真的迷路了。 p,以前是一个常数,现在显然是一个函数。

所以对于类型 7 的分位数,默认...

类型 7

p(k) = (k - 1) / (n - 1)。在这种情况下,p(k) = mode[F(x[k])]。这是 S 使用的。

有人想帮我吗?特别是我对 p 是一个函数和一个常数的符号感到困惑,m 到底是什么,现在要为某些特定的 p 计算 j。

我希望根据这里的答案,我们可以提交一些修改后的文档,以更好地解释这里发生的事情。

quantile.R source code 或输入:quantile.default

【问题讨论】:

    标签: math r statistics


    【解决方案1】:

    当您给它一个向量并且没有已知的 CDF 时,有多种计算分位数的方法。

    考虑以下问题:当您的观察结果不完全落在分位数上时该怎么办。

    “类型”只是决定如何做到这一点。因此,这些方法说,“在 k 阶统计量和 p(k) 之间使用线性插值”。

    那么,什么是 p(k)?一个人说,“好吧,我喜欢使用 k/n”。另一个人说,“我喜欢使用 (k-1)/(n-1)”等。这些方法中的每一种都有不同的属性,更适合一个或另一个问题。

    \alpha 和 \beta 只是参数化函数 p 的方法。在一种情况下,它们是 1 和 1。在另一种情况下,它们是 3/8 和 -1/4。我不认为 p 在文档中是一个常数。他们只是并不总是明确地显示依赖关系。

    看看当你放入像 1:5 和 1:6 这样的向量时,不同类型会发生什么。

    (另请注意,即使您的观察结果恰好落在分位数上,某些类型仍将使用线性插值)。

    【讨论】:

      【解决方案2】:

      你的困惑是可以理解的。那个文档很糟糕。我不得不回到基于 (Hyndman, RJ; Fan, Y. (November 1996). “Sample Quantiles in Statistical Packages”的论文。American Statistician 50 (4): 361–365 .doi:10.2307/2684934) 来了解一下。让我们从第一个问题开始。

      其中 1

      第一部分直接来自论文,但文档作者省略的是j = int(pn+m)。这意味着Q[i](p) 仅取决于最接近p 部分通过(排序)观察的方式的两个顺序统计信息。 (对于像我这样不熟悉这个术语的人来说,一系列观察的“顺序统计”就是排序序列。)

      另外,最后一句话是错误的。它应该是

      这里的gamma取决于np+m的小数部分,g = np+m-j

      至于m,这很简单。 m 取决于选择了 9 种算法中的哪一种。所以就像Q[i]是分位数函数一样,m应该被认为是m[i]。对于算法 1 和 2,m 为 0,对于 3,m 为 -1/2,对于其他算法,下一部分。

      对于连续样本分位数类型(4到9),样本分位数可以通过k阶统计量与p(k)之间的线性插值得到:

      p(k) = (k - alpha) / (n - alpha - beta + 1),其中 α 和 β 是由类型决定的常数。此外,m = alpha + p(1 - alpha - beta),且 gamma = g。

      这真是令人困惑。文档中的 p(k) 与之前的 p 不同。 p(k)plotting position。在论文中,作者将其写为pk,这很有帮助。特别是因为在m 的表达式中,p 是原始的p,而m = alpha + p * (1 - alpha - beta)。从概念上讲,对于算法 4-9,点 (pk, x[k]) 被插值得到解决方案 (p, Q[i](p))。每种算法仅在pk的算法上有所不同。

      至于最后一点,R 只是说明了 S 的用途。

      原始论文给出了 6 个“样本分位数的理想属性”函数的列表,并声明了对 #8 的偏好,它满足所有 1。#5 满足所有这些,但他们不喜欢其他理由(它比从原则派生的更现象学)。 #2 是像我这样的非统计极客会考虑分位数,并且是维基百科中描述的内容。

      顺便说一句,为了回应dreeves answer,Mathematica 的做法明显不同。我想我理解映射。虽然 Mathematica 更容易理解,但 (a) 使用无意义的参数更容易在脚上射击自己,并且 (b) 它不能执行 R 的算法 #2。 (这里是Mathworld's Quantile page,它指出 Mathematica 不能做 #2,但根据四个参数对所有其他算法进行了更简单的概括。)

      【讨论】:

      • 我编写了 quantile() 函数和相关的帮助文件,并于 2004 年 8 月提交给 R 核心团队(替换之前的版本)。我刚刚检查过,所有这些错误都是由于我的帮助文件在我提交后被更改造成的。 (我负责 p 和 p[k] 的使用。)我从来没有注意到它,因为我认为我的文件不会被触及。我会看看是否可以为 R 2.10.0 修复帮助文件。
      • @AFoglia。我已经在robjhyndman.com/quantile.html 提出了一个新的帮助文件。提交给 Rcore 之前的评论?
      • 新的好多了。我有一个小建议,可以为方法 1 到 3 添加 gamma 的定义,尽管这对于具有统计知识的 R 受众来说可能不是必需的。否则,它看起来很棒。
      • 只是为了完成这个讨论,新的帮助文件现在是基础 Rv2.10.0 的一部分。
      • 每次我在 R 中查看 help(quantile) 时,我都对结果感到满意!
      【解决方案3】:

      我相信在@RobHyndman 的评论中提到的修订之后,R 帮助文档很清楚,但我发现它有点压倒性。我发布这个答案以防它帮助某人快速通过选项和他们的假设。

      为了掌握quantile(x, probs=probs),我想查看源代码。这也比我在 R 中预期的要棘手,所以我实际上只是从 github repo 中获取它,它看起来足够新,可以运行。我对默认(类型 7)行为感兴趣,所以我注释了一些,但没有为每个选项做同样的事情。

      您可以在代码中一步一步地看到“类型 7”方法是如何插入的,我还添加了几行来打印一些重要的值。

      quantile.default <-function(x, probs = seq(0, 1, 0.25), na.rm = FALSE, names = TRUE
               , type = 7, ...){
          if(is.factor(x)) { #worry about non-numeric data
              if(!is.ordered(x) || ! type %in% c(1L, 3L))
                  stop("factors are not allowed")
              lx <- levels(x)
          } else lx <- NULL
          if (na.rm){
              x <- x[!is.na(x)]
          } else if (anyNA(x)){
              stop("missing values and NaN's not allowed if 'na.rm' is FALSE")
              }
          eps <- 100*.Machine$double.eps #this is to deal with rounding things sensibly
          if (any((p.ok <- !is.na(probs)) & (probs < -eps | probs > 1+eps)))
              stop("'probs' outside [0,1]")
      
          #####################################
          # here is where terms really used in default type==7 situation get defined
      
          n <- length(x) #how many observations are in sample?
      
          if(na.p <- any(!p.ok)) { # set aside NA & NaN
              o.pr <- probs
              probs <- probs[p.ok]
              probs <- pmax(0, pmin(1, probs)) # allow for slight overshoot
          }
      
          np <- length(probs) #how many quantiles are you computing?
      
          if (n > 0 && np > 0) { #have positive observations and # quantiles to compute
              if(type == 7) { # be completely back-compatible
      
                  index <- 1 + (n - 1) * probs #this gives the order statistic of the quantiles
                  lo <- floor(index)  #this is the observed order statistic just below each quantile
                  hi <- ceiling(index) #above
                  x <- sort(x, partial = unique(c(lo, hi))) #the partial thing is to reduce time to sort, 
                  #and it only guarantees that sorting is "right" at these order statistics, important for large vectors 
                  #ties are not broken and tied elements just stay in their original order
                  qs <- x[lo] #the values associated with the "floor" order statistics
                  i <- which(index > lo) #which of the order statistics for the quantiles do not land on an order statistic for an observed value
      
                  #this is the difference between the order statistic and the available ranks, i think
                  h <- (index - lo)[i] # > 0  by construction 
                  ##      qs[i] <- qs[i] + .minus(x[hi[i]], x[lo[i]]) * (index[i] - lo[i])
                  ##      qs[i] <- ifelse(h == 0, qs[i], (1 - h) * qs[i] + h * x[hi[i]])
                  qs[i] <- (1 - h) * qs[i] + h * x[hi[i]] # This is the interpolation step: assemble the estimated quantile by removing h*low and adding back in h*high. 
                  # h is the arithmetic difference between the desired order statistic amd the available ranks
                  #interpolation only occurs if the desired order statistic is not observed, e.g. .5 quantile is the actual observed median if n is odd. 
                  # This means having a more extreme 99th observation doesn't matter when computing the .75 quantile
      
      
                  ###################################
                  # print all of these things
      
                  cat("floor pos=", c(lo))
                  cat("\nceiling pos=", c(hi))
                  cat("\nfloor values= ", c(x[lo]))
                  cat( "\nwhich floors not targets? ", c(i))
                  cat("\ninterpolate between ", c(x[lo[i]]), ";", c(x[hi[i]]))
                  cat( "\nadjustment values= ", c(h))
                  cat("\nquantile estimates:")
      
          }else if (type <= 3){## Types 1, 2 and 3 are discontinuous sample qs.
                      nppm <- if (type == 3){ n * probs - .5 # n * probs + m; m = -0.5
                      } else {n * probs} # m = 0
      
                      j <- floor(nppm)
                      h <- switch(type,
                                  (nppm > j),     # type 1
                                  ((nppm > j) + 1)/2, # type 2
                                  (nppm != j) | ((j %% 2L) == 1L)) # type 3
      
                      } else{
                      ## Types 4 through 9 are continuous sample qs.
                      switch(type - 3,
                             {a <- 0; b <- 1},    # type 4
                             a <- b <- 0.5,   # type 5
                             a <- b <- 0,     # type 6
                             a <- b <- 1,     # type 7 (unused here)
                             a <- b <- 1 / 3, # type 8
                             a <- b <- 3 / 8) # type 9
                      ## need to watch for rounding errors here
                      fuzz <- 4 * .Machine$double.eps
                      nppm <- a + probs * (n + 1 - a - b) # n*probs + m
                      j <- floor(nppm + fuzz) # m = a + probs*(1 - a - b)
                      h <- nppm - j
      
                      if(any(sml <- abs(h) < fuzz)) h[sml] <- 0
      
                  x <- sort(x, partial =
                                unique(c(1, j[j>0L & j<=n], (j+1)[j>0L & j<n], n))
                  )
                  x <- c(x[1L], x[1L], x, x[n], x[n])
                  ## h can be zero or one (types 1 to 3), and infinities matter
                  ####        qs <- (1 - h) * x[j + 2] + h * x[j + 3]
                  ## also h*x might be invalid ... e.g. Dates and ordered factors
                  qs <- x[j+2L]
                  qs[h == 1] <- x[j+3L][h == 1]
                  other <- (0 < h) & (h < 1)
                  if(any(other)) qs[other] <- ((1-h)*x[j+2L] + h*x[j+3L])[other]
      
                  } 
          } else {
              qs <- rep(NA_real_, np)}
      
          if(is.character(lx)){
              qs <- factor(qs, levels = seq_along(lx), labels = lx, ordered = TRUE)}
          if(names && np > 0L) {
              names(qs) <- format_perc(probs)
          }
          if(na.p) { # do this more elegantly (?!)
              o.pr[p.ok] <- qs
              names(o.pr) <- rep("", length(o.pr)) # suppress <NA> names
              names(o.pr)[p.ok] <- names(qs)
              o.pr
          } else qs
      }
      
      ####################
      
      # fake data
      x<-c(1,2,2,2,3,3,3,4,4,4,4,4,5,5,5,5,5,5,5,5,5,6,6,7,99)
      y<-c(1,2,2,2,3,3,3,4,4,4,4,4,5,5,5,5,5,5,5,5,5,6,6,7,9)
      z<-c(1,2,2,2,3,3,3,4,4,4,4,4,5,5,5,5,5,5,5,5,5,6,6,7)
      
      #quantiles "of interest"
      probs<-c(0.5, 0.75, 0.95, 0.975)
      
      # a tiny bit of illustrative behavior
      quantile.default(x,probs=probs, names=F)
      quantile.default(y,probs=probs, names=F) #only difference is .975 quantile since that is driven by highest 2 observations
      quantile.default(z,probs=probs, names=F) # This shifts everything b/c now none of the quantiles fall on an observation (and of course the distribution changed...)... but 
      #.75 quantile is stil 5.0 b/c the observations just above and below the order statistic for that quantile are still 5. However, it got there for a different reason.
      
      #how does rescaling affect quantile estimates?
      sqrt(quantile.default(x^2, probs=probs, names=F))
      exp(quantile.default(log(x), probs=probs, names=F))
      

      【讨论】:

      • quantile.default()源代码的详细解释非常有用,非常感谢
      猜你喜欢
      • 2015-04-11
      • 1970-01-01
      • 2015-01-22
      • 2015-08-04
      • 2021-03-19
      • 2019-02-09
      • 2018-05-10
      • 2016-01-11
      • 2018-01-23
      相关资源
      最近更新 更多