Skip to content

Instantly share code, notes, and snippets.

@Protonk
Last active January 2, 2016 12:39
Show Gist options
  • Save Protonk/8304852 to your computer and use it in GitHub Desktop.
Save Protonk/8304852 to your computer and use it in GitHub Desktop.
d3.quantile = function(values, p) {
  var H = (values.length - 1) * p + 1,
      h = Math.floor(H),
      v = +values[h - 1],
      e = H - h;
  return e ? v + e * (values[h] - v) : v;
};

Vaues is a sorted array with N values, and p is the percentile to find the closest value to. So if we want the median, we'd pass in 0.5. This function is basically 1 (potentially 2) linear interpolations. The first occurs when we determine H. If the values in the array were uniformly distributed, the term (N * p) will be ~ the pth element in the array.

We get our N values in the first line, and multiply it by our percentile then add one. So we'll always get >= 1.

Flooring this gives us a useful index. For an evenly divisble N, where floor is a no-op (e.g. an even N when we want the median, so p = 1/2, H = 5 and h = H.), it's the index one above the percentile we want. The residue will be 0, which is falsy.

For an index which can't be easily divisible, the residue of H - h is truthy. and we interpolate a value based on the 'distance' between h and H.

If the index is divisble, the residue is falsey and we return the value corresponding to values[H - 1].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment