为什么不同的百分位数给出相同的值?

Why do different percentiles give the same value?

我试图计算卡方分布值列表的 10 个百分位数。我使用 "chi-squared" 是因为我认为这最接近我们的真实数据。

现在我尝试逐步执行此操作,以免遗漏任何内容。

import numpy as np
values =  np.array([int(w)*10 for w in list(np.random.chisquare(6,1000))])
print('Min: ', np.max(values))
print('Max: ', np.min(values))
print('Mean: ', np.mean(values))

for p in [w*10 for w in range(1,11,1)]:
    percentile = np.percentile(values,p)
    print(p,percentile)

这是上面代码的示例输出:

Min:  0
Max:  230
Mean:  55.49
Percent: 10 Percentile:  20.0
Percent: 20 Percentile:  30.0
Percent: 30 Percentile:  30.0
Percent: 40 Percentile:  40.0
Percent: 50 Percentile:  50.0
Percent: 60 Percentile:  60.0
Percent: 70 Percentile:  70.0
Percent: 80 Percentile:  80.0
Percent: 90 Percentile:  100.0
Percent: 100 Percentile:  230.0

我纠结的一点是:
为什么我得到相同的 "Percentile" 20% 和 30%?
我一直认为 20 / 30 意味着:20% 的值低于以下值(在本例中为 30)。就像 100% 的值低于最大值 230。

我缺少哪个想法?

因为values是用表达式int(w)*10创建的,所有的值都是10的整数倍。这意味着大部分值都重复了很多次。例如,我只是 运行 那个代码,发现值 30 被重复了 119 次。事实证明,当您计算值时,分位数间隔 20% - 30% 包含 值 30。这就是为什么值 30 在输出中重复的原因。

我可以将我的数据集分解为

   value    #
     0     14
    10     72
    20    100
    30    119
    40    152
    etc.

将其分成 100 个一组(因为您有 1000 个值,并且您正在查看 10%、20% 等)。

                                                np.percentile
Percent  Group       Values (counts)            (largest value in previous column)
-------  ---------   ------------------------   ----------------------------------
10       0 - 99      0 (14), 10 (72), 20 (16)    20
20       100 - 199   20 (84), 30 (16)            30
30       200 - 299   30 (100)                    30
40       300 - 399   30 (3), 40 (97)             40
etc.

鉴于您使用的分布,此输出似乎是最有可能的,但如果您重新运行 代码足够多次,您将遇到不同的输出。我只是 运行 又得到了

10 20.0
20 20.0
30 30.0
40 40.0
50 50.0
60 50.0
70 60.0
80 80.0
90 100.0
100 210.0

请注意,20.0 和 50.0 都是重复的。此 运行 的值计数为:

In [56]: values, counts = np.unique(values, return_counts=True)                                                             

In [57]: values                                                                                                             
Out[57]: 
array([  0,  10,  20,  30,  40,  50,  60,  70,  80,  90, 100, 110, 120,
       130, 140, 150, 160, 170, 180, 190, 210])

In [58]: counts                                                                                                             
Out[58]: 
array([ 14,  73, 129, 134, 134, 119, 105,  67,  73,  33,  41,  21,  19,
        16,   8,   7,   1,   2,   2,   1,   1])