首页 / 知识

关于数学:解释R中的quantile()函数

2023-04-17 07:07:00

关于数学:解释R中的quantile()函数

Explain the quantile() function in R

我一整天都被 R 分位数函数迷惑了。

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

来自文档:

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

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

where 1 = i = 9, (j-m)/n = p
(j-m+1)/ n, x[j] is the jth order
statistic, n is the sample size, and m
is a constant determined by the sample
quantile type. Here gamma depends on
the fractional part of g = np+m-j.

那么,如何计算j?米?

For the continuous sample quantile
types (4 through 9), the sample
quantiles can be obtained by linear
interpolation between the kth order
statistic and p(k):

p(k) = (k - alpha) / (n - alpha - beta
+ 1),
where ?± and ?2 are constants determined
by the type. Further, m = alpha + p(1
- alpha - beta), and gamma = g.

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

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

Type 7

p(k) = (k - 1) / (n - 1). In this case, p(k) = mode[F(x[k])]. This is used by S.

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

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

quantile.R 源代码
或输入:quantile.default


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

where 1 = i = 9, (j-m)/n = p (j-m+1)/ n, x[j] is the jth order statistic, n is the sample size, and m is a constant determined by the sample quantile type. Here gamma depends on the fractional part of g = np+m-j.

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

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

Here gamma depends on the fractional part of np+m, g = np+m-j

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

For the continuous sample quantile types (4 through 9), the sample quantiles can be obtained by linear interpolation between the kth order statistic and p(k):

p(k) = (k - alpha) / (n - alpha - beta + 1), where ?± and ?2 are constants determined by the type. Further, m = alpha + p(1 - alpha - beta), and gamma = g.

这真是令人困惑。文档所称的 p(k) 与之前的 p 不同。 p(k) 是绘图位置。在论文中,作者将其写为 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 的回答,Mathematica 的做法明显不同。我想我理解映射。虽然 Mathematica 更容易理解,但 (a) 使用无意义的参数更容易在脚上射击自己,并且 (b) 它不能执行 R 的算法 #2。 (这里是 Mathworld 的分位数页面,其中指出 Mathematica 不能做 #2,但根据四个参数对所有其他算法进行了更简单的概括。)


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

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

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

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

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

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

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


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

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

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

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
141
142
143
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("\
ceiling pos=", c(hi))
            cat("\
floor values=", c(x[lo]))
            cat("\
which floors not targets?", c(i))
            cat("\
interpolate between", c(x[lo[i]]),";", c(x[hi[i]]))
            cat("\
adjustment values=", c(h))
            cat("\
quantile 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[j0L & j=n], (j+1)[j0L & jn], 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))

函数解释工作原理文档

最新内容

相关内容

猜你喜欢