1 | import Aggregate from './Aggregate';
|
2 | import {ValidAggregateOps} from './util/AggregateOps';
|
3 | import {accessor, accessorFields, inherits} from 'vega-util';
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | export default function Pivot(params) {
|
22 | Aggregate.call(this, params);
|
23 | }
|
24 |
|
25 | Pivot.Definition = {
|
26 | 'type': 'Pivot',
|
27 | 'metadata': {'generates': true, 'changes': true},
|
28 | 'params': [
|
29 | { 'name': 'groupby', 'type': 'field', 'array': true },
|
30 | { 'name': 'field', 'type': 'field', 'required': true },
|
31 | { 'name': 'value', 'type': 'field', 'required': true },
|
32 | { 'name': 'op', 'type': 'enum', 'values': ValidAggregateOps, 'default': 'sum' },
|
33 | { 'name': 'limit', 'type': 'number', 'default': 0 },
|
34 | { 'name': 'key', 'type': 'field' }
|
35 | ]
|
36 | };
|
37 |
|
38 | var prototype = inherits(Pivot, Aggregate);
|
39 |
|
40 | prototype._transform = prototype.transform;
|
41 |
|
42 | prototype.transform = function(_, pulse) {
|
43 | return this._transform(aggregateParams(_, pulse), pulse);
|
44 | };
|
45 |
|
46 |
|
47 |
|
48 |
|
49 | function aggregateParams(_, pulse) {
|
50 | var key = _.field,
|
51 | value = _.value,
|
52 | op = (_.op === 'count' ? '__count__' : _.op) || 'sum',
|
53 | fields = accessorFields(key).concat(accessorFields(value)),
|
54 | keys = pivotKeys(key, _.limit || 0, pulse);
|
55 |
|
56 |
|
57 |
|
58 | if (pulse.changed()) _.set('__pivot__', null, null, true);
|
59 |
|
60 | return {
|
61 | key: _.key,
|
62 | groupby: _.groupby,
|
63 | ops: keys.map(function() { return op; }),
|
64 | fields: keys.map(function(k) { return get(k, key, value, fields); }),
|
65 | as: keys.map(function(k) { return k + ''; }),
|
66 | modified: _.modified.bind(_)
|
67 | };
|
68 | }
|
69 |
|
70 |
|
71 |
|
72 | function get(k, key, value, fields) {
|
73 | return accessor(
|
74 | function(d) { return key(d) === k ? value(d) : NaN; },
|
75 | fields,
|
76 | k + ''
|
77 | );
|
78 | }
|
79 |
|
80 |
|
81 | function pivotKeys(key, limit, pulse) {
|
82 | var map = {},
|
83 | list = [];
|
84 |
|
85 | pulse.visit(pulse.SOURCE, function(t) {
|
86 | var k = key(t);
|
87 | if (!map[k]) {
|
88 | map[k] = 1;
|
89 | list.push(k);
|
90 | }
|
91 | });
|
92 |
|
93 |
|
94 | list.sort(function(u, v) {
|
95 | return (u<v||u==null) && v!=null ? -1
|
96 | : (u>v||v==null) && u!=null ? 1
|
97 | : ((v=v instanceof Date?+v:v),(u=u instanceof Date?+u:u))!==u && v===v ? -1
|
98 | : v!==v && u===u ? 1 : 0;
|
99 | });
|
100 |
|
101 | return limit ? list.slice(0, limit) : list;
|
102 | }
|