-
Notifications
You must be signed in to change notification settings - Fork 4
/
aggregate.js
78 lines (72 loc) · 2.58 KB
/
aggregate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"use strict";
/**
* Places the data into buckets according to the category returned by the
* aggregator function.
* @param {Array} data the array of data points
* @param {function: Object -> String} aggregator given a data point, this
* function returns the bucket it should be in
* @return {Object} of the form: { "<bucket>": [{data point}, {data point}, ...] }
*/
exports.aggregateData = function(data, aggregator) {
var aggregatedData = {};
data.forEach(function(current) {
var category = aggregator(current);
if(! (category in aggregatedData)) {
aggregatedData[category] = [];
}
aggregatedData[category].push(current);
});
return aggregatedData;
};
/**
* Works like aggregateData, but data can be placed in multiple buckets.
* @param {Array} data
* @param {function: Object -> Array[String]} aggregator
* @return {Object}
* @see aggregateData
*/
exports.aggregateMultiple = function(data, aggregator) {
var aggregatedData = {};
data.forEach(function(current) {
var categories = aggregator(current);
categories.forEach(function(category) {
if(! (category in aggregatedData)) {
aggregatedData[category] = [];
}
aggregatedData[category].push(current);
});
});
return aggregatedData;
};
/**
* Returns the median value of the given array.
* @param {Array} array an array of numeric values
* @return {Number} the median value of the array (middle value, or mean of
* middle values)
*/
exports.median = function(array) {
array.sort();
var center = Math.floor(array.length / 2);
if(array.length % 2 === 1) {
return array[center];
} else {
return (array[center-1] + array[center]) / 2;
}
};
/**
* Summarizes data by reducing all data in a category to a single value.
* The result is an array of objects, each having a "category" and a "value".
* The array is sorted by category name.
* @param {Object} aggregatedData "bucketized" data
* @param {function: Array -> ?} summarizer a function that reduces an array of
* data points to a single value
* @return {Array} an array of summarized data points: objects containing a
* category and a value: [{category: '<category>', value: <value>}, ...]
*/
exports.summarizeData = function(aggregatedData, summarizer) {
var categories = Object.keys(aggregatedData).sort();
return categories.map(function(category) {
var categoryData = aggregatedData[category];
return { category: category, value: summarizer(categoryData) };
});
};