timeseries-aggregate
Advanced tools
+51
-2
@@ -8,3 +8,3 @@ // Constants | ||
| // Calculate an array of sums over the specified periods | ||
| var aggregate = function(endDate, numPeriods, periodDurationInMs, series) { | ||
| var sum = function(endDate, numPeriods, periodDurationInMs, series) { | ||
| var iterator = new Date(endDate.getTime() - periodDurationInMs), | ||
@@ -51,4 +51,53 @@ sumByPeriod = [], | ||
| // Calculate an average of values over the specified periods | ||
| var average = function(endDate, numPeriods, periodDurationInMs, series) { | ||
| var iterator = new Date(endDate.getTime() - periodDurationInMs), | ||
| averageByPeriod = [], | ||
| period = iterator, | ||
| sum = 0, | ||
| count = 0, | ||
| point, | ||
| t; | ||
| for (var i = series.length - 1; i >= 0; --i) { | ||
| point = series[i]; | ||
| t = point.timestamp; | ||
| // Skip runs that are after the ending date | ||
| if (t >= endDate) { | ||
| continue; | ||
| } | ||
| // Skip runs older than the cutoff | ||
| if (t < endDate - (periodDurationInMs * numPeriods)) { | ||
| break; | ||
| } | ||
| // Account for periods with no data at all | ||
| while (t < iterator) { | ||
| iterator = new Date(iterator.getTime() - periodDurationInMs); | ||
| averageByPeriod.unshift({ | ||
| period: period, | ||
| average: (count > 0 ? sum / count : 0) | ||
| }); | ||
| period = iterator; | ||
| sum = 0; | ||
| count = 0; | ||
| } | ||
| // Collect data | ||
| sum += point.value; | ||
| count += 1; | ||
| } | ||
| averageByPeriod.unshift({ | ||
| period: period, | ||
| average: (count > 0 ? sum / count : 0) | ||
| }); | ||
| return averageByPeriod; | ||
| }; | ||
| module.exports = { | ||
| aggregate: aggregate, | ||
| sum: sum, | ||
| average: average, | ||
| MINUTE_IN_MS: MINUTE_IN_MS, | ||
@@ -55,0 +104,0 @@ HOUR_IN_MS: HOUR_IN_MS, |
+1
-1
| { | ||
| "name": "timeseries-aggregate", | ||
| "version": "0.0.1", | ||
| "version": "0.0.2", | ||
| "author": "Daniel Sauble", | ||
@@ -5,0 +5,0 @@ "description": "Given a set of timeseries data, produce an array of sums over multiple data intervals", |
+18
-13
@@ -1,7 +0,6 @@ | ||
| Given an array of timeseries data ordered from oldest to | ||
| newest, aggregate the sum of X periods of Y milliseconds | ||
| each, ending at the date given. | ||
| Given an array of timeseries data ordered from oldest to newest, aggregate | ||
| the sum or average of values inside X periods of Y milliseconds each, ending | ||
| at the date given. | ||
| Series data is expected to be an array of objects of the | ||
| following format: | ||
| Series data is expected to be an array of objects of the following format: | ||
@@ -13,20 +12,26 @@ { | ||
| The output is an array of objects of the following format: | ||
| The output of summation is an array of objects of the following format: | ||
| { | ||
| period: Date, // The start of the period being sum | ||
| period: Date, // The start of the period being summed | ||
| sum: Number // The sum of values in the period | ||
| } | ||
| This algorithm is weighted toward sums that favor the end of | ||
| the series array (most recent values), as it iterates from | ||
| end to start. | ||
| The output of averaging is an array of objects of the following format: | ||
| { | ||
| period: Date, // The start of the period being averaged | ||
| average: Number // The average of values in the period | ||
| } | ||
| This algorithm is weighted toward calculations that favor the end of the series | ||
| array (most recent values), as it iterates from end to start. | ||
| ## Usage | ||
| var DateSum = require('../index'); | ||
| var Aggregate = require('../index'); | ||
| var endDate = new Date("June 9, 2016 GMT-0000"), | ||
| numPeriods = 2, | ||
| periodDurationInMs = DateSum.DAY_IN_MS * 2, | ||
| periodDurationInMs = Aggregate.DAY_IN_MS * 2, | ||
| series = [ | ||
@@ -84,2 +89,2 @@ { | ||
| // Aggregate the two 48-hour periods preceeding June 9th | ||
| DateSum.aggregate(endDate, numPeriods, periodDurationInMs, series); | ||
| Aggregate.sum(endDate, numPeriods, periodDurationInMs, series); |
+69
-5
@@ -9,3 +9,3 @@ (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){ | ||
| // Calculate an array of sums over the specified periods | ||
| var aggregate = function(endDate, numPeriods, periodDurationInMs, series) { | ||
| var sum = function(endDate, numPeriods, periodDurationInMs, series) { | ||
| var iterator = new Date(endDate.getTime() - periodDurationInMs), | ||
@@ -52,4 +52,53 @@ sumByPeriod = [], | ||
| // Calculate an average of values over the specified periods | ||
| var average = function(endDate, numPeriods, periodDurationInMs, series) { | ||
| var iterator = new Date(endDate.getTime() - periodDurationInMs), | ||
| averageByPeriod = [], | ||
| period = iterator, | ||
| sum = 0, | ||
| count = 0, | ||
| point, | ||
| t; | ||
| for (var i = series.length - 1; i >= 0; --i) { | ||
| point = series[i]; | ||
| t = point.timestamp; | ||
| // Skip runs that are after the ending date | ||
| if (t >= endDate) { | ||
| continue; | ||
| } | ||
| // Skip runs older than the cutoff | ||
| if (t < endDate - (periodDurationInMs * numPeriods)) { | ||
| break; | ||
| } | ||
| // Account for periods with no data at all | ||
| while (t < iterator) { | ||
| iterator = new Date(iterator.getTime() - periodDurationInMs); | ||
| averageByPeriod.unshift({ | ||
| period: period, | ||
| average: (count > 0 ? sum / count : 0) | ||
| }); | ||
| period = iterator; | ||
| sum = 0; | ||
| count = 0; | ||
| } | ||
| // Collect data | ||
| sum += point.value; | ||
| count += 1; | ||
| } | ||
| averageByPeriod.unshift({ | ||
| period: period, | ||
| average: (count > 0 ? sum / count : 0) | ||
| }); | ||
| return averageByPeriod; | ||
| }; | ||
| module.exports = { | ||
| aggregate: aggregate, | ||
| sum: sum, | ||
| average: average, | ||
| MINUTE_IN_MS: MINUTE_IN_MS, | ||
@@ -62,6 +111,6 @@ HOUR_IN_MS: HOUR_IN_MS, | ||
| },{}],2:[function(require,module,exports){ | ||
| var DateSum = require('../index'); | ||
| var Aggregate = require('../index'); | ||
| QUnit.test( 'Calculate sums over two 48-hour periods', function(assert) { | ||
| var sums = DateSum.aggregate(endDate, numPeriods, periodDurationInMs, series); | ||
| var sums = Aggregate.sum(endDate, numPeriods, periodDurationInMs, series); | ||
@@ -80,5 +129,20 @@ assert.deepEqual(sums, [ | ||
| QUnit.test( 'Calculate averages over two 48-hour periods', function(assert) { | ||
| var averages = Aggregate.average(endDate, numPeriods, periodDurationInMs, series); | ||
| assert.deepEqual(averages, [ | ||
| { | ||
| period: p1, | ||
| average: 5.5 | ||
| }, | ||
| { | ||
| period: p2, | ||
| average: 7.5 | ||
| } | ||
| ], 'Passed!'); | ||
| }); | ||
| var endDate = new Date("June 9, 2016 GMT-0000"), | ||
| numPeriods = 2, | ||
| periodDurationInMs = DateSum.DAY_IN_MS * 2, | ||
| periodDurationInMs = Aggregate.DAY_IN_MS * 2, | ||
| p1 = new Date("June 5, 2016 GMT-0000"), | ||
@@ -85,0 +149,0 @@ p2 = new Date("June 7, 2016 GMT-0000"), |
+18
-3
@@ -1,5 +0,5 @@ | ||
| var DateSum = require('../index'); | ||
| var Aggregate = require('../index'); | ||
| QUnit.test( 'Calculate sums over two 48-hour periods', function(assert) { | ||
| var sums = DateSum.aggregate(endDate, numPeriods, periodDurationInMs, series); | ||
| var sums = Aggregate.sum(endDate, numPeriods, periodDurationInMs, series); | ||
@@ -18,5 +18,20 @@ assert.deepEqual(sums, [ | ||
| QUnit.test( 'Calculate averages over two 48-hour periods', function(assert) { | ||
| var averages = Aggregate.average(endDate, numPeriods, periodDurationInMs, series); | ||
| assert.deepEqual(averages, [ | ||
| { | ||
| period: p1, | ||
| average: 5.5 | ||
| }, | ||
| { | ||
| period: p2, | ||
| average: 7.5 | ||
| } | ||
| ], 'Passed!'); | ||
| }); | ||
| var endDate = new Date("June 9, 2016 GMT-0000"), | ||
| numPeriods = 2, | ||
| periodDurationInMs = DateSum.DAY_IN_MS * 2, | ||
| periodDurationInMs = Aggregate.DAY_IN_MS * 2, | ||
| p1 = new Date("June 5, 2016 GMT-0000"), | ||
@@ -23,0 +38,0 @@ p2 = new Date("June 7, 2016 GMT-0000"), |
13639
30.13%377
41.2%89
5.95%