dc
Version:
A multi-dimensional charting library built to work natively with crossfilter and rendered using d3.js
1,391 lines (1,229 loc) • 38.8 kB
JavaScript
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.reductio=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
(function (global){
var reductio_build = require('./build.js');
var reductio_accessors = require('./accessors.js');
var reductio_parameters = require('./parameters.js');
var reductio_postprocess = require('./postprocess');
var crossfilter = (typeof window !== "undefined" ? window['crossfilter'] : typeof global !== "undefined" ? global['crossfilter'] : null);
function reductio() {
var parameters = reductio_parameters();
var funcs = {};
function my(group) {
// Start fresh each time.
funcs = {
reduceAdd: function(p) { return p; },
reduceRemove: function(p) { return p; },
reduceInitial: function () { return {}; },
};
reductio_build.build(parameters, funcs);
// If we're doing groupAll
if(parameters.groupAll) {
if(group.top) {
console.warn("'groupAll' is defined but attempting to run on a standard dimension.group(). Must run on dimension.groupAll().");
} else {
var bisect = crossfilter.bisect.by(function(d) { return d.key; }).left;
var i, j;
var keys;
var keysLength;
var k; // Key
group.reduce(
function(p, v, nf) {
keys = parameters.groupAll(v);
keysLength = keys.length;
for(j=0;j<keysLength;j++) {
k = keys[j];
i = bisect(p, k, 0, p.length);
if(!p[i] || p[i].key !== k) {
// If the group doesn't yet exist, create it first.
p.splice(i, 0, { key: k, value: funcs.reduceInitial() });
}
// Then pass the record and the group value to the reducers
funcs.reduceAdd(p[i].value, v, nf);
}
return p;
},
function(p, v, nf) {
keys = parameters.groupAll(v);
keysLength = keys.length;
for(j=0;j<keysLength;j++) {
i = bisect(p, keys[j], 0, p.length);
// The group should exist or we're in trouble!
// Then pass the record and the group value to the reducers
funcs.reduceRemove(p[i].value, v, nf);
}
return p;
},
function() {
return [];
}
);
if(!group.all) {
// Add an 'all' method for compatibility with standard Crossfilter groups.
group.all = function() { return this.value(); };
}
}
} else {
group.reduce(funcs.reduceAdd, funcs.reduceRemove, funcs.reduceInitial);
}
reductio_postprocess(group, parameters, funcs);
return group;
}
reductio_accessors.build(my, parameters);
return my;
}
require('./postprocessors')(reductio);
reductio_postprocess = reductio_postprocess(reductio);
module.exports = reductio;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./accessors.js":2,"./build.js":6,"./parameters.js":19,"./postprocess":20,"./postprocessors":21}],2:[function(require,module,exports){
var reductio_parameters = require('./parameters.js');
_assign = function assign(target) {
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
for (var index = 1; index < arguments.length; ++index) {
var source = arguments[index];
if (source != null) {
for (var nextKey in source) {
if(source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
function accessor_build(obj, p) {
// obj.order = function(value) {
// if (!arguments.length) return p.order;
// p.order = value;
// return obj;
// };
// Converts a string to an accessor function
function accessorify(v) {
if( typeof v === 'string' ) {
// Rewrite to a function
var tempValue = v;
var func = function (d) { return d[tempValue]; }
return func;
} else {
return v;
}
}
// Converts a string to an accessor function
function accessorifyNumeric(v) {
if( typeof v === 'string' ) {
// Rewrite to a function
var tempValue = v;
var func = function (d) { return +d[tempValue]; }
return func;
} else {
return v;
}
}
obj.fromObject = function(value) {
if(!arguments.length) return p;
_assign(p, value);
return obj;
};
obj.toObject = function() {
return p;
};
obj.count = function(value, propName) {
if (!arguments.length) return p.count;
if (!propName) {
propName = 'count';
}
p.count = propName;
return obj;
};
obj.sum = function(value) {
if (!arguments.length) return p.sum;
value = accessorifyNumeric(value);
p.sum = value;
return obj;
};
obj.avg = function(value) {
if (!arguments.length) return p.avg;
value = accessorifyNumeric(value);
// We can take an accessor function, a boolean, or a string
if( typeof value === 'function' ) {
if(p.sum && p.sum !== value) console.warn('SUM aggregation is being overwritten by AVG aggregation');
p.sum = value;
p.avg = true;
p.count = 'count';
} else {
p.avg = value;
}
return obj;
};
obj.exception = function(value) {
if (!arguments.length) return p.exceptionAccessor;
value = accessorify(value);
p.exceptionAccessor = value;
return obj;
};
obj.filter = function(value) {
if (!arguments.length) return p.filter;
p.filter = value;
return obj;
};
obj.valueList = function(value) {
if (!arguments.length) return p.valueList;
value = accessorify(value);
p.valueList = value;
return obj;
};
obj.median = function(value) {
if (!arguments.length) return p.median;
value = accessorifyNumeric(value);
if(typeof value === 'function') {
if(p.valueList && p.valueList !== value) console.warn('VALUELIST accessor is being overwritten by median aggregation');
p.valueList = value;
}
p.median = value;
return obj;
};
obj.min = function(value) {
if (!arguments.length) return p.min;
value = accessorifyNumeric(value);
if(typeof value === 'function') {
if(p.valueList && p.valueList !== value) console.warn('VALUELIST accessor is being overwritten by min aggregation');
p.valueList = value;
}
p.min = value;
return obj;
};
obj.max = function(value) {
if (!arguments.length) return p.max;
value = accessorifyNumeric(value);
if(typeof value === 'function') {
if(p.valueList && p.valueList !== value) console.warn('VALUELIST accessor is being overwritten by max aggregation');
p.valueList = value;
}
p.max = value;
return obj;
};
obj.exceptionCount = function(value) {
if (!arguments.length) return p.exceptionCount;
value = accessorify(value);
if( typeof value === 'function' ) {
if(p.exceptionAccessor && p.exceptionAccessor !== value) console.warn('EXCEPTION accessor is being overwritten by exception count aggregation');
p.exceptionAccessor = value;
p.exceptionCount = true;
} else {
p.exceptionCount = value;
}
return obj;
};
obj.exceptionSum = function(value) {
if (!arguments.length) return p.exceptionSum;
value = accessorifyNumeric(value);
p.exceptionSum = value;
return obj;
};
obj.histogramValue = function(value) {
if (!arguments.length) return p.histogramValue;
value = accessorifyNumeric(value);
p.histogramValue = value;
return obj;
};
obj.histogramBins = function(value) {
if (!arguments.length) return p.histogramThresholds;
p.histogramThresholds = value;
return obj;
};
obj.std = function(value) {
if (!arguments.length) return p.std;
value = accessorifyNumeric(value);
if(typeof(value) === 'function') {
p.sumOfSquares = value;
p.sum = value;
p.count = 'count';
p.std = true;
} else {
p.std = value;
}
return obj;
};
obj.sumOfSq = function(value) {
if (!arguments.length) return p.sumOfSquares;
value = accessorifyNumeric(value);
p.sumOfSquares = value;
return obj;
};
obj.value = function(value, accessor) {
if (!arguments.length || typeof value !== 'string' ) {
console.error("'value' requires a string argument.");
} else {
if(!p.values) p.values = {};
p.values[value] = {};
p.values[value].parameters = reductio_parameters();
accessor_build(p.values[value], p.values[value].parameters);
if(accessor) p.values[value].accessor = accessor;
return p.values[value];
}
};
obj.nest = function(keyAccessorArray) {
if(!arguments.length) return p.nestKeys;
keyAccessorArray.map(accessorify);
p.nestKeys = keyAccessorArray;
return obj;
};
obj.alias = function(propAccessorObj) {
if(!arguments.length) return p.aliasKeys;
p.aliasKeys = propAccessorObj;
return obj;
};
obj.aliasProp = function(propAccessorObj) {
if(!arguments.length) return p.aliasPropKeys;
p.aliasPropKeys = propAccessorObj;
return obj;
};
obj.groupAll = function(groupTest) {
if(!arguments.length) return p.groupAll;
p.groupAll = groupTest;
return obj;
};
obj.dataList = function(value) {
if (!arguments.length) return p.dataList;
p.dataList = value;
return obj;
};
obj.custom = function(addRemoveInitialObj) {
if (!arguments.length) return p.custom;
p.custom = addRemoveInitialObj;
return obj;
};
}
var reductio_accessors = {
build: accessor_build
};
module.exports = reductio_accessors;
},{"./parameters.js":19}],3:[function(require,module,exports){
var reductio_alias = {
initial: function(prior, path, obj) {
return function (p) {
if(prior) p = prior(p);
function buildAliasFunction(key){
return function(){
return obj[key](path(p));
};
}
for(var prop in obj) {
path(p)[prop] = buildAliasFunction(prop);
}
return p;
};
}
};
module.exports = reductio_alias;
},{}],4:[function(require,module,exports){
var reductio_alias_prop = {
add: function (obj, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
for(var prop in obj) {
path(p)[prop] = obj[prop](path(p),v);
}
return p;
};
}
};
module.exports = reductio_alias_prop;
},{}],5:[function(require,module,exports){
var reductio_avg = {
add: function (a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
if(path(p).count > 0) {
path(p).avg = path(p).sum / path(p).count;
} else {
path(p).avg = 0;
}
return p;
};
},
remove: function (a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
if(path(p).count > 0) {
path(p).avg = path(p).sum / path(p).count;
} else {
path(p).avg = 0;
}
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).avg = 0;
return p;
};
}
};
module.exports = reductio_avg;
},{}],6:[function(require,module,exports){
var reductio_filter = require('./filter.js');
var reductio_count = require('./count.js');
var reductio_sum = require('./sum.js');
var reductio_avg = require('./avg.js');
var reductio_median = require('./median.js');
var reductio_min = require('./min.js');
var reductio_max = require('./max.js');
var reductio_value_count = require('./value-count.js');
var reductio_value_list = require('./value-list.js');
var reductio_exception_count = require('./exception-count.js');
var reductio_exception_sum = require('./exception-sum.js');
var reductio_histogram = require('./histogram.js');
var reductio_sum_of_sq = require('./sum-of-squares.js');
var reductio_std = require('./std.js');
var reductio_nest = require('./nest.js');
var reductio_alias = require('./alias.js');
var reductio_alias_prop = require('./aliasProp.js');
var reductio_data_list = require('./data-list.js');
var reductio_custom = require('./custom.js');
function build_function(p, f, path) {
// We have to build these functions in order. Eventually we can include dependency
// information and create a dependency graph if the process becomes complex enough.
if(!path) path = function (d) { return d; };
// Keep track of the original reducers so that filtering can skip back to
// them if this particular value is filtered out.
var origF = {
reduceAdd: f.reduceAdd,
reduceRemove: f.reduceRemove,
reduceInitial: f.reduceInitial
};
if(p.count || p.std) {
f.reduceAdd = reductio_count.add(f.reduceAdd, path, p.count);
f.reduceRemove = reductio_count.remove(f.reduceRemove, path, p.count);
f.reduceInitial = reductio_count.initial(f.reduceInitial, path, p.count);
}
if(p.sum) {
f.reduceAdd = reductio_sum.add(p.sum, f.reduceAdd, path);
f.reduceRemove = reductio_sum.remove(p.sum, f.reduceRemove, path);
f.reduceInitial = reductio_sum.initial(f.reduceInitial, path);
}
if(p.avg) {
if(!p.count || !p.sum) {
console.error("You must set .count(true) and define a .sum(accessor) to use .avg(true).");
} else {
f.reduceAdd = reductio_avg.add(p.sum, f.reduceAdd, path);
f.reduceRemove = reductio_avg.remove(p.sum, f.reduceRemove, path);
f.reduceInitial = reductio_avg.initial(f.reduceInitial, path);
}
}
// The unique-only reducers come before the value_count reducers. They need to check if
// the value is already in the values array on the group. They should only increment/decrement
// counts if the value not in the array or the count on the value is 0.
if(p.exceptionCount) {
if(!p.exceptionAccessor) {
console.error("You must define an .exception(accessor) to use .exceptionCount(true).");
} else {
f.reduceAdd = reductio_exception_count.add(p.exceptionAccessor, f.reduceAdd, path);
f.reduceRemove = reductio_exception_count.remove(p.exceptionAccessor, f.reduceRemove, path);
f.reduceInitial = reductio_exception_count.initial(f.reduceInitial, path);
}
}
if(p.exceptionSum) {
if(!p.exceptionAccessor) {
console.error("You must define an .exception(accessor) to use .exceptionSum(accessor).");
} else {
f.reduceAdd = reductio_exception_sum.add(p.exceptionAccessor, p.exceptionSum, f.reduceAdd, path);
f.reduceRemove = reductio_exception_sum.remove(p.exceptionAccessor, p.exceptionSum, f.reduceRemove, path);
f.reduceInitial = reductio_exception_sum.initial(f.reduceInitial, path);
}
}
// Maintain the values array.
if(p.valueList || p.median || p.min || p.max) {
f.reduceAdd = reductio_value_list.add(p.valueList, f.reduceAdd, path);
f.reduceRemove = reductio_value_list.remove(p.valueList, f.reduceRemove, path);
f.reduceInitial = reductio_value_list.initial(f.reduceInitial, path);
}
// Maintain the data array.
if(p.dataList) {
f.reduceAdd = reductio_data_list.add(p.dataList, f.reduceAdd, path);
f.reduceRemove = reductio_data_list.remove(p.dataList, f.reduceRemove, path);
f.reduceInitial = reductio_data_list.initial(f.reduceInitial, path);
}
if(p.median) {
f.reduceAdd = reductio_median.add(f.reduceAdd, path);
f.reduceRemove = reductio_median.remove(f.reduceRemove, path);
f.reduceInitial = reductio_median.initial(f.reduceInitial, path);
}
if(p.min) {
f.reduceAdd = reductio_min.add(f.reduceAdd, path);
f.reduceRemove = reductio_min.remove(f.reduceRemove, path);
f.reduceInitial = reductio_min.initial(f.reduceInitial, path);
}
if(p.max) {
f.reduceAdd = reductio_max.add(f.reduceAdd, path);
f.reduceRemove = reductio_max.remove(f.reduceRemove, path);
f.reduceInitial = reductio_max.initial(f.reduceInitial, path);
}
// Maintain the values count array.
if(p.exceptionAccessor) {
f.reduceAdd = reductio_value_count.add(p.exceptionAccessor, f.reduceAdd, path);
f.reduceRemove = reductio_value_count.remove(p.exceptionAccessor, f.reduceRemove, path);
f.reduceInitial = reductio_value_count.initial(f.reduceInitial, path);
}
// Histogram
if(p.histogramValue && p.histogramThresholds) {
f.reduceAdd = reductio_histogram.add(p.histogramValue, f.reduceAdd, path);
f.reduceRemove = reductio_histogram.remove(p.histogramValue, f.reduceRemove, path);
f.reduceInitial = reductio_histogram.initial(p.histogramThresholds ,f.reduceInitial, path);
}
// Sum of Squares
if(p.sumOfSquares) {
f.reduceAdd = reductio_sum_of_sq.add(p.sumOfSquares, f.reduceAdd, path);
f.reduceRemove = reductio_sum_of_sq.remove(p.sumOfSquares, f.reduceRemove, path);
f.reduceInitial = reductio_sum_of_sq.initial(f.reduceInitial, path);
}
// Standard deviation
if(p.std) {
if(!p.sumOfSquares || !p.sum) {
console.error("You must set .sumOfSq(accessor) and define a .sum(accessor) to use .std(true). Or use .std(accessor).");
} else {
f.reduceAdd = reductio_std.add(f.reduceAdd, path);
f.reduceRemove = reductio_std.remove(f.reduceRemove, path);
f.reduceInitial = reductio_std.initial(f.reduceInitial, path);
}
}
// Custom reducer defined by 3 functions : add, remove, initial
if (p.custom) {
f.reduceAdd = reductio_custom.add(f.reduceAdd, path, p.custom.add);
f.reduceRemove = reductio_custom.remove(f.reduceRemove, path, p.custom.remove);
f.reduceInitial = reductio_custom.initial(f.reduceInitial, path, p.custom.initial);
}
// Nesting
if(p.nestKeys) {
f.reduceAdd = reductio_nest.add(p.nestKeys, f.reduceAdd, path);
f.reduceRemove = reductio_nest.remove(p.nestKeys, f.reduceRemove, path);
f.reduceInitial = reductio_nest.initial(f.reduceInitial, path);
}
// Alias functions
if(p.aliasKeys) {
f.reduceInitial = reductio_alias.initial(f.reduceInitial, path, p.aliasKeys);
}
// Alias properties - this is less efficient than alias functions
if(p.aliasPropKeys) {
f.reduceAdd = reductio_alias_prop.add(p.aliasPropKeys, f.reduceAdd, path);
// This isn't a typo. The function is the same for add/remove.
f.reduceRemove = reductio_alias_prop.add(p.aliasPropKeys, f.reduceRemove, path);
}
// Filters determine if our built-up priors should run, or if it should skip
// back to the filters given at the beginning of this build function.
if (p.filter) {
f.reduceAdd = reductio_filter.add(p.filter, f.reduceAdd, origF.reduceAdd, path);
f.reduceRemove = reductio_filter.remove(p.filter, f.reduceRemove, origF.reduceRemove, path);
}
// Values go last.
if(p.values) {
Object.getOwnPropertyNames(p.values).forEach(function(n) {
// Set up the path on each group.
var setupPath = function(prior) {
return function (p) {
p = prior(p);
path(p)[n] = {};
return p;
};
};
f.reduceInitial = setupPath(f.reduceInitial);
build_function(p.values[n].parameters, f, function (p) { return p[n]; });
});
}
}
var reductio_build = {
build: build_function
};
module.exports = reductio_build;
},{"./alias.js":3,"./aliasProp.js":4,"./avg.js":5,"./count.js":8,"./custom.js":9,"./data-list.js":10,"./exception-count.js":11,"./exception-sum.js":12,"./filter.js":13,"./histogram.js":14,"./max.js":15,"./median.js":16,"./min.js":17,"./nest.js":18,"./std.js":23,"./sum-of-squares.js":24,"./sum.js":25,"./value-count.js":26,"./value-list.js":27}],7:[function(require,module,exports){
var pluck = function(n){
return function(d){
return d[n];
};
};
// supported operators are sum, avg, and count
_grouper = function(path, prior){
if(!path) path = function(d){return d;};
return function(p, v){
if(prior) prior(p, v);
var x = path(p), y = path(v);
if(typeof y.count !== 'undefined') x.count += y.count;
if(typeof y.sum !== 'undefined') x.sum += y.sum;
if(typeof y.avg !== 'undefined') x.avg = x.sum/x.count;
return p;
};
};
reductio_cap = function (prior, f, p) {
var obj = f.reduceInitial();
// we want to support values so we'll need to know what those are
var values = p.values ? Object.keys(p.values) : [];
var _othersGrouper = _grouper();
if (values.length) {
for (var i = 0; i < values.length; ++i) {
_othersGrouper = _grouper(pluck(values[i]), _othersGrouper);
}
}
return function (cap, othersName) {
if (!arguments.length) return prior();
if( cap === Infinity || !cap ) return prior();
var all = prior();
var slice_idx = cap-1;
if(all.length <= cap) return all;
var data = all.slice(0, slice_idx);
var others = {key: othersName || 'Others'};
others.value = f.reduceInitial();
for (var i = slice_idx; i < all.length; ++i) {
_othersGrouper(others.value, all[i].value);
}
data.push(others);
return data;
};
};
module.exports = reductio_cap;
},{}],8:[function(require,module,exports){
var reductio_count = {
add: function(prior, path, propName) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p)[propName]++;
return p;
};
},
remove: function(prior, path, propName) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p)[propName]--;
return p;
};
},
initial: function(prior, path, propName) {
return function (p) {
if(prior) p = prior(p);
// if(p === undefined) p = {};
path(p)[propName] = 0;
return p;
};
}
};
module.exports = reductio_count;
},{}],9:[function(require,module,exports){
var reductio_custom = {
add: function(prior, path, addFn) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
return addFn(p, v);
};
},
remove: function(prior, path, removeFn) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
return removeFn(p, v);
};
},
initial: function(prior, path, initialFn) {
return function (p) {
if(prior) p = prior(p);
return initialFn(p);
};
}
};
module.exports = reductio_custom;
},{}],10:[function(require,module,exports){
var reductio_data_list = {
add: function(a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).dataList.push(v);
return p;
};
},
remove: function(a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).dataList.splice(path(p).dataList.indexOf(v), 1);
return p;
};
},
initial: function(prior, path) {
return function (p) {
if(prior) p = prior(p);
path(p).dataList = [];
return p;
};
}
};
module.exports = reductio_data_list;
},{}],11:[function(require,module,exports){
var reductio_exception_count = {
add: function (a, prior, path) {
var i, curr;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Only count++ if the p.values array doesn't contain a(v) or if it's 0.
i = path(p).bisect(path(p).values, a(v), 0, path(p).values.length);
curr = path(p).values[i];
if((!curr || curr[0] !== a(v)) || curr[1] === 0) {
path(p).exceptionCount++;
}
return p;
};
},
remove: function (a, prior, path) {
var i, curr;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Only count-- if the p.values array contains a(v) value of 1.
i = path(p).bisect(path(p).values, a(v), 0, path(p).values.length);
curr = path(p).values[i];
if(curr && curr[0] === a(v) && curr[1] === 1) {
path(p).exceptionCount--;
}
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).exceptionCount = 0;
return p;
};
}
};
module.exports = reductio_exception_count;
},{}],12:[function(require,module,exports){
var reductio_exception_sum = {
add: function (a, sum, prior, path) {
var i, curr;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Only sum if the p.values array doesn't contain a(v) or if it's 0.
i = path(p).bisect(path(p).values, a(v), 0, path(p).values.length);
curr = path(p).values[i];
if((!curr || curr[0] !== a(v)) || curr[1] === 0) {
path(p).exceptionSum = path(p).exceptionSum + sum(v);
}
return p;
};
},
remove: function (a, sum, prior, path) {
var i, curr;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Only sum if the p.values array contains a(v) value of 1.
i = path(p).bisect(path(p).values, a(v), 0, path(p).values.length);
curr = path(p).values[i];
if(curr && curr[0] === a(v) && curr[1] === 1) {
path(p).exceptionSum = path(p).exceptionSum - sum(v);
}
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).exceptionSum = 0;
return p;
};
}
};
module.exports = reductio_exception_sum;
},{}],13:[function(require,module,exports){
var reductio_filter = {
// The big idea here is that you give us a filter function to run on values,
// a 'prior' reducer to run (just like the rest of the standard reducers),
// and a reference to the last reducer (called 'skip' below) defined before
// the most recent chain of reducers. This supports individual filters for
// each .value('...') chain that you add to your reducer.
add: function (filter, prior, skip) {
return function (p, v, nf) {
if (filter(v, nf)) {
if (prior) prior(p, v, nf);
} else {
if (skip) skip(p, v, nf);
}
return p;
};
},
remove: function (filter, prior, skip) {
return function (p, v, nf) {
if (filter(v, nf)) {
if (prior) prior(p, v, nf);
} else {
if (skip) skip(p, v, nf);
}
return p;
};
}
};
module.exports = reductio_filter;
},{}],14:[function(require,module,exports){
(function (global){
var crossfilter = (typeof window !== "undefined" ? window['crossfilter'] : typeof global !== "undefined" ? global['crossfilter'] : null);
var reductio_histogram = {
add: function (a, prior, path) {
var bisect = crossfilter.bisect.by(function(d) { return d; }).left;
var bisectHisto = crossfilter.bisect.by(function(d) { return d.x; }).right;
var curr;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
curr = path(p).histogram[bisectHisto(path(p).histogram, a(v), 0, path(p).histogram.length) - 1];
curr.y++;
curr.splice(bisect(curr, a(v), 0, curr.length), 0, a(v));
return p;
};
},
remove: function (a, prior, path) {
var bisect = crossfilter.bisect.by(function(d) { return d; }).left;
var bisectHisto = crossfilter.bisect.by(function(d) { return d.x; }).right;
var curr;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
curr = path(p).histogram[bisectHisto(path(p).histogram, a(v), 0, path(p).histogram.length) - 1];
curr.y--;
curr.splice(bisect(curr, a(v), 0, curr.length), 1);
return p;
};
},
initial: function (thresholds, prior, path) {
return function (p) {
p = prior(p);
path(p).histogram = [];
var arr = [];
for(var i = 1; i < thresholds.length; i++) {
arr = [];
arr.x = thresholds[i - 1];
arr.dx = (thresholds[i] - thresholds[i - 1]);
arr.y = 0;
path(p).histogram.push(arr);
}
return p;
};
}
};
module.exports = reductio_histogram;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],15:[function(require,module,exports){
var reductio_max = {
add: function (prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).max = path(p).valueList[path(p).valueList.length - 1];
return p;
};
},
remove: function (prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Check for undefined.
if(path(p).valueList.length === 0) {
path(p).max = undefined;
return p;
}
path(p).max = path(p).valueList[path(p).valueList.length - 1];
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).max = undefined;
return p;
};
}
};
module.exports = reductio_max;
},{}],16:[function(require,module,exports){
var reductio_median = {
add: function (prior, path) {
var half;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
half = Math.floor(path(p).valueList.length/2);
if(path(p).valueList.length % 2) {
path(p).median = path(p).valueList[half];
} else {
path(p).median = (path(p).valueList[half-1] + path(p).valueList[half]) / 2.0;
}
return p;
};
},
remove: function (prior, path) {
var half;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
half = Math.floor(path(p).valueList.length/2);
// Check for undefined.
if(path(p).valueList.length === 0) {
path(p).median = undefined;
return p;
}
if(path(p).valueList.length === 1 || path(p).valueList.length % 2) {
path(p).median = path(p).valueList[half];
} else {
path(p).median = (path(p).valueList[half-1] + path(p).valueList[half]) / 2.0;
}
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).median = undefined;
return p;
};
}
};
module.exports = reductio_median;
},{}],17:[function(require,module,exports){
var reductio_min = {
add: function (prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).min = path(p).valueList[0];
return p;
};
},
remove: function (prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Check for undefined.
if(path(p).valueList.length === 0) {
path(p).min = undefined;
return p;
}
path(p).min = path(p).valueList[0];
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).min = undefined;
return p;
};
}
};
module.exports = reductio_min;
},{}],18:[function(require,module,exports){
(function (global){
var crossfilter = (typeof window !== "undefined" ? window['crossfilter'] : typeof global !== "undefined" ? global['crossfilter'] : null);
var reductio_nest = {
add: function (keyAccessors, prior, path) {
var i; // Current key accessor
var arrRef;
var newRef;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
arrRef = path(p).nest;
keyAccessors.forEach(function(a) {
newRef = arrRef.filter(function(d) { return d.key === a(v); })[0];
if(newRef) {
// There is another level.
arrRef = newRef.values;
} else {
// Next level doesn't yet exist so we create it.
newRef = [];
arrRef.push({ key: a(v), values: newRef });
arrRef = newRef;
}
});
arrRef.push(v);
return p;
};
},
remove: function (keyAccessors, prior, path) {
var arrRef;
var nextRef;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
arrRef = path(p).nest;
keyAccessors.forEach(function(a) {
arrRef = arrRef.filter(function(d) { return d.key === a(v); })[0].values;
});
// Array contains an actual reference to the row, so just splice it out.
arrRef.splice(arrRef.indexOf(v), 1);
// If the leaf now has length 0 and it's not the base array remove it.
// TODO
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).nest = [];
return p;
};
}
};
module.exports = reductio_nest;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],19:[function(require,module,exports){
var reductio_parameters = function() {
return {
order: false,
avg: false,
count: false,
sum: false,
exceptionAccessor: false,
exceptionCount: false,
exceptionSum: false,
filter: false,
valueList: false,
median: false,
histogramValue: false,
min: false,
max: false,
histogramThresholds: false,
std: false,
sumOfSquares: false,
values: false,
nestKeys: false,
aliasKeys: false,
aliasPropKeys: false,
groupAll: false,
dataList: false,
custom: false
};
};
module.exports = reductio_parameters;
},{}],20:[function(require,module,exports){
function postProcess(reductio) {
return function (group, p, f) {
group.post = function(){
var postprocess = function () {
return postprocess.all();
};
postprocess.all = function () {
return group.all();
};
var postprocessors = reductio.postprocessors;
Object.keys(postprocessors).forEach(function (name) {
postprocess[name] = function () {
var _all = postprocess.all;
var args = [].slice.call(arguments);
postprocess.all = function () {
return postprocessors[name](_all, f, p).apply(null, args);
};
return postprocess;
};
});
return postprocess;
};
};
}
module.exports = postProcess;
},{}],21:[function(require,module,exports){
module.exports = function(reductio){
reductio.postprocessors = {};
reductio.registerPostProcessor = function(name, func){
reductio.postprocessors[name] = func;
};
reductio.registerPostProcessor('cap', require('./cap'));
reductio.registerPostProcessor('sortBy', require('./sortBy'));
};
},{"./cap":7,"./sortBy":22}],22:[function(require,module,exports){
var pluck_n = function (n) {
if (typeof n === 'function') {
return n;
}
if (~n.indexOf('.')) {
var split = n.split('.');
return function (d) {
return split.reduce(function (p, v) {
return p[v];
}, d);
};
}
return function (d) {
return d[n];
};
};
function ascending(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
var comparer = function (accessor, ordering) {
return function (a, b) {
return ordering(accessor(a), accessor(b));
};
};
var type = {}.toString;
module.exports = function (prior) {
return function (value, order) {
if (arguments.length === 1) {
order = ascending;
}
return prior().sort(comparer(pluck_n(value), order));
};
};
},{}],23:[function(require,module,exports){
var reductio_std = {
add: function (prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
if(path(p).count > 0) {
path(p).std = 0.0;
var n = path(p).sumOfSq - path(p).sum*path(p).sum/path(p).count;
if (n>0.0) path(p).std = Math.sqrt(n/(path(p).count-1));
} else {
path(p).std = 0.0;
}
return p;
};
},
remove: function (prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
if(path(p).count > 0) {
path(p).std = 0.0;
var n = path(p).sumOfSq - path(p).sum*path(p).sum/path(p).count;
if (n>0.0) path(p).std = Math.sqrt(n/(path(p).count-1));
} else {
path(p).std = 0;
}
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).std = 0;
return p;
};
}
};
module.exports = reductio_std;
},{}],24:[function(require,module,exports){
var reductio_sum_of_sq = {
add: function (a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).sumOfSq = path(p).sumOfSq + a(v)*a(v);
return p;
};
},
remove: function (a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).sumOfSq = path(p).sumOfSq - a(v)*a(v);
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).sumOfSq = 0;
return p;
};
}
};
module.exports = reductio_sum_of_sq;
},{}],25:[function(require,module,exports){
var reductio_sum = {
add: function (a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).sum = path(p).sum + a(v);
return p;
};
},
remove: function (a, prior, path) {
return function (p, v, nf) {
if(prior) prior(p, v, nf);
path(p).sum = path(p).sum - a(v);
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).sum = 0;
return p;
};
}
};
module.exports = reductio_sum;
},{}],26:[function(require,module,exports){
(function (global){
var crossfilter = (typeof window !== "undefined" ? window['crossfilter'] : typeof global !== "undefined" ? global['crossfilter'] : null);
var reductio_value_count = {
add: function (a, prior, path) {
var i, curr;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Not sure if this is more efficient than sorting.
i = path(p).bisect(path(p).values, a(v), 0, path(p).values.length);
curr = path(p).values[i];
if(curr && curr[0] === a(v)) {
// Value already exists in the array - increment it
curr[1]++;
} else {
// Value doesn't exist - add it in form [value, 1]
path(p).values.splice(i, 0, [a(v), 1]);
}
return p;
};
},
remove: function (a, prior, path) {
var i;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
i = path(p).bisect(path(p).values, a(v), 0, path(p).values.length);
// Value already exists or something has gone terribly wrong.
path(p).values[i][1]--;
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
// Array[Array[value, count]]
path(p).values = [];
path(p).bisect = crossfilter.bisect.by(function(d) { return d[0]; }).left;
return p;
};
}
};
module.exports = reductio_value_count;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],27:[function(require,module,exports){
(function (global){
var crossfilter = (typeof window !== "undefined" ? window['crossfilter'] : typeof global !== "undefined" ? global['crossfilter'] : null);
var reductio_value_list = {
add: function (a, prior, path) {
var i;
var bisect = crossfilter.bisect.by(function(d) { return d; }).left;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
// Not sure if this is more efficient than sorting.
i = bisect(path(p).valueList, a(v), 0, path(p).valueList.length);
path(p).valueList.splice(i, 0, a(v));
return p;
};
},
remove: function (a, prior, path) {
var i;
var bisect = crossfilter.bisect.by(function(d) { return d; }).left;
return function (p, v, nf) {
if(prior) prior(p, v, nf);
i = bisect(path(p).valueList, a(v), 0, path(p).valueList.length);
// Value already exists or something has gone terribly wrong.
path(p).valueList.splice(i, 1);
return p;
};
},
initial: function (prior, path) {
return function (p) {
p = prior(p);
path(p).valueList = [];
return p;
};
}
};
module.exports = reductio_value_list;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[1])(1)
});