lamchau
10/31/2015 - 7:46 PM

stats.js

function Stats(data, precision) {
  var PRECISION = precision || 2;
  var length = data.length;

  var mean = (function() {
    var sum = data.reduce(function(a, b) {
      return a + b;
    }, 0);
    return sum / length;
  })();

  var median = (function() {
    var sorted = data.slice().sort();
    var index = Math.ceil((length - 1) / 2);
    var median = 0;
    if (length % 2 === 0) {
      median = (sorted[index - 1] + sorted[index]) / 2;
    } else {
      median = sorted[index];
    }
    return median;
  })();

  var variance = (function() {
    return data.reduce(function(accumulator, value) {
      return accumulator + Math.pow(value - mean, 2);
    }, 0) / length;
  })();

  var stdev = Math.sqrt(variance);

  var results = {
    mean: mean.toFixed(PRECISION),
    median: median.toFixed(PRECISION),
    variance: variance.toFixed(PRECISION),
    stdev: stdev.toFixed(PRECISION)
  };

  var keys = Object.keys(results);
  results.summary = function() {
    return keys.reduce(function(array, key) {
      array.push(key + ": " + results[key]);
      return array;
    }, []).join(", ");
  };
  return results;
}

function test(data, expected) {
  var stats = Stats(data);
  var result = ["mean", "median", "variance", "stdev"].every(function(key) {
    return stats[key] == expected[key];
  });
  console.log(result ? "ok:" : "failed:", data);
}

test([1, 2, 3, 4, 5, 6], {
  mean: 3.50,
  median: 3.50,
  variance: 2.92,
  stdev: 1.71
});

test([1, 1, 2, 5, 6, 6, 9], {
  mean: 4.29,
  median: 5.00,
  variance: 7.92,
  stdev: 2.81
});