UNPKG

vega-transforms

Version:

Data processing transforms for Vega dataflows.

79 lines (68 loc) 2.6 kB
import {partition} from './util/util.js'; import {Transform, ingest} from 'vega-dataflow'; import {quantiles} from 'vega-statistics'; import {accessorName, inherits} from 'vega-util'; import {range} from 'd3-array'; /** * Generates sample quantile values from an input data stream. * @constructor * @param {object} params - The parameters for this operator. * @param {function(object): *} params.field - An accessor for the data field * over which to calculate quantile values. * @param {Array<function(object): *>} [params.groupby] - An array of accessors * to groupby. * @param {Array<number>} [params.probs] - An array of probabilities in * the range (0, 1) for which to compute quantile values. If not specified, * the *step* parameter will be used. * @param {Array<number>} [params.step=0.01] - A probability step size for * sampling quantile values. All values from one-half the step size up to * 1 (exclusive) will be sampled. This parameter is only used if the * *quantiles* parameter is not provided. */ export default function Quantile(params) { Transform.call(this, null, params); } Quantile.Definition = { 'type': 'Quantile', 'metadata': {'generates': true, 'changes': true}, 'params': [ { 'name': 'groupby', 'type': 'field', 'array': true }, { 'name': 'field', 'type': 'field', 'required': true }, { 'name': 'probs', 'type': 'number', 'array': true }, { 'name': 'step', 'type': 'number', 'default': 0.01 }, { 'name': 'as', 'type': 'string', 'array': true, 'default': ['prob', 'value'] } ] }; const EPSILON = 1e-14; inherits(Quantile, Transform, { transform(_, pulse) { const out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS), as = _.as || ['prob', 'value']; if (this.value && !_.modified() && !pulse.changed()) { out.source = this.value; return out; } const source = pulse.materialize(pulse.SOURCE).source, groups = partition(source, _.groupby, _.field), names = (_.groupby || []).map(accessorName), values = [], step = _.step || 0.01, p = _.probs || range(step/2, 1 - EPSILON, step), n = p.length; groups.forEach(g => { const q = quantiles(g, p); for (let i=0; i<n; ++i) { const t = {}; for (let i=0; i<names.length; ++i) { t[names[i]] = g.dims[i]; } t[as[0]] = p[i]; t[as[1]] = q[i]; values.push(ingest(t)); } }); if (this.value) out.rem = this.value; this.value = out.add = out.source = values; return out; } });