UNPKG

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
!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) });