d3 / d3-array

Array manipulation, ordering, searching, summarizing, etc.
https://d3js.org/d3-array
ISC License
454 stars 187 forks source link

Weighted quantiles? #47

Open mbostock opened 7 years ago

mbostock commented 7 years ago

I tend to do something like this, but it’s pretty inefficient and requires integer weights:

var values = d3.merge(samples.map(s => d3.range(weight(s)).map(() => value(s))));

A related question is how to expose weighted quantiles as a scale.

Fil commented 4 years ago

Implemented in https://observablehq.com/d/f7139ebca0286081

it's a bit less performant than d3.quantile since I used sort instead of quickselect. (It might be possible to use quickselect iteratively. [EDIT:] it's probably too difficult, I'm giving up on this aspect.)

Fil commented 4 years ago

Also, not sure about the API. The typical use case might be with data=[{value, weight},…] so we would need two accessors. But then, when we have an array of weights (as in the notebook), it would be a clunky accessor (_,i) => weights[i].

Fil commented 4 years ago

I added a note about the interpolation method—I'm using R-2, not R-7. My thinking here is that the (possibly non-integer) weights do not correspond to repeated point samples that have by chance yielded the same value, but rather represent contiguous classes (or blocks) of a certain width.

image

We want to interpolate the value only when we are exactly on the edge between two blocks.

Fil commented 4 years ago

The API now allows for an optional accessor (last argument of the function), weights can be specified as an accessor or an iterable, and values as an iterable.