d3.quantile 似乎错误地计算了 Q1

d3.quantile seems to be calculating Q1 incorrectly

我将 24 个数字的排序数组提供给 d3.quantile 并要求它计算第一个四分位数值。由于数组可以平均分为四组 6 个值,我的假设是结果将是 arr[5] 和 arr[6] 的平均值,但这不是我得到的结果。

var arr = [89.7, 93.2, 94, 94.3, 94.5, 95.4, 95.9, 96.1, 96.4, 96.5, 96.9, 96.9, 97.3, 97.6, 97.6, 97.6, 97.8, 98.3, 98.3, 98.4, 98.5, 98.5, 98.6, 98.6];
var myAssumption = (arr[5] + arr[6]) / 2;   // 95.65
var d3Result = d3.quantile(arr, 0.25);      // 95.775

d3 分位数函数是否使用了一些更复杂的算法? This Wikipedia article 列出了几个选项,但我不确定正在使用哪个(或者为什么一种算法优于另一种算法)。

结果没有错,是预期值。

如果您查看链接的那个 Wikipedia 页面,您会在 类型 列中看到 "R-7"(写为 "R-7, Excel, SciPy-(1,1), Maple-6")。这是 d3.quantile() 函数使用的算法。

看看d3.quantile()的源代码:

export default function(values, p, valueof) {
    if (valueof == null) valueof = number;
    if (!(n = values.length)) return;
    if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values);
    if (p >= 1) return +valueof(values[n - 1], n - 1, values);
    var n,
        i = (n - 1) * p,
        i0 = Math.floor(i),
        value0 = +valueof(values[i0], i0, values),
        value1 = +valueof(values[i0 + 1], i0 + 1, values);
    return value0 + (value1 - value0) * (i - i0);
}

因此,对于您的情况,我们将有:

i = (24 - 1) * 0.25
//   ^--- the length of the array

这给了我们 5.75(和 5 作为 Math.floor(i))。

则返回值(即函数中的value0 + (value1 - value0) * (i - i0))为:

95.4 + (95.9 - 95.4) * (5.75 - 5)

这为我们提供了您所看到的结果:

95.775

这是 运行 演示:

var arr = [89.7, 93.2, 94, 94.3, 94.5, 95.4, 95.9, 96.1, 96.4, 96.5, 96.9, 96.9, 97.3, 97.6, 97.6, 97.6, 97.8, 98.3, 98.3, 98.4, 98.5, 98.5, 98.6, 98.6];
var d3Result = d3.quantile(arr, 0.25);
console.log(d3Result)
<script src="https://d3js.org/d3.v4.min.js"></script>