UNPKG

2.56 kBJavaScriptView Raw
1import {partition} from './util/util';
2import {Transform, ingest} from 'vega-dataflow';
3import {quantiles} from 'vega-statistics';
4import {accessorName, inherits} from 'vega-util';
5import {range} from 'd3-array';
6
7/**
8 * Generates sample quantile values from an input data stream.
9 * @constructor
10 * @param {object} params - The parameters for this operator.
11 * @param {function(object): *} params.field - An accessor for the data field
12 * over which to calculate quantile values.
13 * @param {Array<function(object): *>} [params.groupby] - An array of accessors
14 * to groupby.
15 * @param {Array<number>} [params.probs] - An array of probabilities in
16 * the range (0, 1) for which to compute quantile values. If not specified,
17 * the *step* parameter will be used.
18 * @param {Array<number>} [params.step=0.01] - A probability step size for
19 * sampling quantile values. All values from one-half the step size up to
20 * 1 (exclusive) will be sampled. This parameter is only used if the
21 * *quantiles* parameter is not provided.
22 */
23export default function Quantile(params) {
24 Transform.call(this, null, params);
25}
26
27Quantile.Definition = {
28 'type': 'Quantile',
29 'metadata': {'generates': true, 'changes': true},
30 'params': [
31 { 'name': 'groupby', 'type': 'field', 'array': true },
32 { 'name': 'field', 'type': 'field', 'required': true },
33 { 'name': 'probs', 'type': 'number', 'array': true },
34 { 'name': 'step', 'type': 'number', 'default': 0.01 },
35 { 'name': 'as', 'type': 'string', 'array': true, 'default': ['prob', 'value'] }
36 ]
37};
38
39var prototype = inherits(Quantile, Transform);
40
41var EPSILON = 1e-14;
42
43prototype.transform = function(_, pulse) {
44 var out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
45 as = _.as || ['prob', 'value'];
46
47 if (this.value && !_.modified() && !pulse.changed()) {
48 out.source = this.value;
49 return out;
50 }
51
52 const source = pulse.materialize(pulse.SOURCE).source,
53 groups = partition(source, _.groupby, _.field),
54 names = (_.groupby || []).map(accessorName),
55 values = [],
56 step = _.step || 0.01,
57 p = _.probs || range(step/2, 1 - EPSILON, step),
58 n = p.length;
59
60 groups.forEach(g => {
61 const q = quantiles(g, p);
62
63 for (let i=0; i<n; ++i) {
64 const t = {};
65 for (let i=0; i<names.length; ++i) {
66 t[names[i]] = g.dims[i];
67 }
68 t[as[0]] = p[i];
69 t[as[1]] = q[i];
70 values.push(ingest(t));
71 }
72 });
73
74 if (this.value) out.rem = this.value;
75 this.value = out.add = out.source = values;
76
77 return out;
78};