| <!DOCTYPE html> |
| <!-- |
| Copyright 2016 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| <link rel="import" href="/tracing/base/range.html"> |
| <script> |
| 'use strict'; |
| |
| tr.exportTo('tr.b', function() { |
| |
| /*** |
| * An object of this class computes basic statistics online in O(1). |
| * Usage: |
| * 1. Create an instance. |
| * 2. Add numbers using the |add| method. |
| * 3. Query statistics. |
| * 4. Repeat from step 2. |
| * |
| * @constructor |
| */ |
| function RunningStatistics() { |
| this.mean_ = 0; |
| this.count_ = 0; |
| this.max_ = -Infinity; |
| this.min_ = Infinity; |
| this.sum_ = 0; |
| this.variance_ = 0; |
| } |
| |
| RunningStatistics.prototype = { |
| get count() { |
| return this.count_; |
| }, |
| |
| get mean() { |
| if (this.count_ == 0) |
| return undefined; |
| return this.mean_; |
| }, |
| |
| get max() { |
| return this.max_; |
| }, |
| |
| get min() { |
| return this.min_; |
| }, |
| |
| get sum() { |
| return this.sum_; |
| }, |
| |
| get variance() { |
| if (this.count_ == 0) |
| return undefined; |
| if (this.count_ == 1) |
| return 0; |
| return this.variance_ / (this.count_ - 1); |
| }, |
| |
| get stddev() { |
| if (this.count_ == 0) |
| return undefined; |
| return Math.sqrt(this.variance); |
| }, |
| |
| add: function(x) { |
| this.count_++; |
| this.max_ = Math.max(this.max_, x); |
| this.min_ = Math.min(this.min_, x); |
| this.sum_ += x; |
| // The following uses Welford's algorithm for computing running mean |
| // and variance. See http://www.johndcook.com/blog/standard_deviation. |
| if (this.count_ === 1) { |
| this.mean_ = x; |
| this.variance_ = 0; |
| } else { |
| var oldMean = this.mean_; |
| var oldVariance = this.variance_; |
| this.mean_ = oldMean + (x - oldMean) / this.count_; |
| this.variance_ = oldVariance + (x - oldMean) * (x - this.mean_); |
| } |
| }, |
| |
| merge: function(other) { |
| var result = new RunningStatistics(); |
| result.count_ = this.count_ + other.count_; |
| result.sum_ = this.sum_ + other.sum_; |
| result.min_ = Math.min(this.min_, other.min_); |
| result.max_ = Math.max(this.max_, other.max_); |
| if (other.count_ === 0 && this.count_ === 0) { |
| result.mean_ = 0; |
| result.variance_ = 0; |
| } else { |
| // Combine the mean and the variance using the formulas from |
| // https://goo.gl/ddcAep. |
| var mx = this.mean_, my = other.mean_; |
| var vx = this.variance_, vy = other.variance_; |
| var n = this.count_, m = other.count_; |
| result.mean_ = (n * mx + m * my) / (n + m); |
| result.variance_ = vx + vy + n * m * (mx - my) * (mx - my) / (n + m); |
| } |
| return result; |
| }, |
| |
| asDict: function() { |
| return { |
| mean: this.mean_, |
| count: this.count_, |
| max: this.max_, |
| min: this.min_, |
| sum: this.sum_, |
| variance: this.variance_ |
| }; |
| } |
| }; |
| |
| RunningStatistics.fromDict = function(d) { |
| var result = new RunningStatistics(); |
| result.mean_ = d.mean; |
| result.count_ = d.count; |
| result.max_ = d.max; |
| result.min_ = d.min; |
| result.sum_ = d.sum; |
| result.variance_ = d.variance; |
| return result; |
| }; |
| |
| return { |
| RunningStatistics: RunningStatistics |
| }; |
| }); |
| </script> |