| "use strict"; |
| |
| var assert = require('assert'); |
| var Statistics = require('../public/shared/statistics.js'); |
| if (!assert.almostEqual) |
| assert.almostEqual = require('./resources/almost-equal.js'); |
| |
| |
| describe('assert.almostEqual', function () { |
| it('should not throw when values are identical', function () { |
| assert.doesNotThrow(function () { assert.almostEqual(1, 1); }); |
| }); |
| |
| it('should not throw when values are close', function () { |
| assert.doesNotThrow(function () { assert.almostEqual(1.10, 1.107, 2); }); |
| assert.doesNotThrow(function () { assert.almostEqual(1256.7, 1256.72, 4); }); |
| }); |
| |
| it('should throw when values are not close', function () { |
| assert.throws(function () { assert.almostEqual(1.10, 1.27, 2); }); |
| assert.throws(function () { assert.almostEqual(735.4, 735.6, 4); }); |
| }); |
| }); |
| |
| describe('Statistics', function () { |
| describe('min', function () { |
| it('should find the mininum value', function () { |
| assert.equal(Statistics.min([1, 2, 3, 4]), 1); |
| assert.equal(Statistics.min([4, 3, 2, 1]), 1); |
| assert.equal(Statistics.min([2000, 20, 200]), 20); |
| assert.equal(Statistics.min([0.3, 0.06, 0.5]), 0.06); |
| assert.equal(Statistics.min([-0.3, 0.06, 0.5]), -0.3); |
| assert.equal(Statistics.min([-0.3, 0.06, 0.5, Infinity]), -0.3); |
| assert.equal(Statistics.min([-0.3, 0.06, 0.5, -Infinity]), -Infinity); |
| assert.equal(Statistics.min([]), Infinity); |
| }); |
| }); |
| |
| describe('max', function () { |
| it('should find the mininum value', function () { |
| assert.equal(Statistics.max([1, 2, 3, 4]), 4); |
| assert.equal(Statistics.max([4, 3, 2, 1]), 4); |
| assert.equal(Statistics.max([2000, 20, 200]), 2000); |
| assert.equal(Statistics.max([0.3, 0.06, 0.5]), 0.5); |
| assert.equal(Statistics.max([-0.3, 0.06, 0.5]), 0.5); |
| assert.equal(Statistics.max([-0.3, 0.06, 0.5, Infinity]), Infinity); |
| assert.equal(Statistics.max([-0.3, 0.06, 0.5, -Infinity]), 0.5); |
| assert.equal(Statistics.max([]), -Infinity); |
| }); |
| }); |
| |
| describe('sum', function () { |
| it('should find the sum of values', function () { |
| assert.equal(Statistics.sum([1, 2, 3, 4]), 10); |
| assert.equal(Statistics.sum([4, 3, 2, 1]), 10); |
| assert.equal(Statistics.sum([2000, 20, 200]), 2220); |
| assert.equal(Statistics.sum([0.3, 0.06, 0.5]), 0.86); |
| assert.equal(Statistics.sum([-0.3, 0.06, 0.5]), 0.26); |
| assert.equal(Statistics.sum([-0.3, 0.06, 0.5, Infinity]), Infinity); |
| assert.equal(Statistics.sum([-0.3, 0.06, 0.5, -Infinity]), -Infinity); |
| assert.equal(Statistics.sum([]), 0); |
| }); |
| }); |
| |
| |
| describe('weightedMean',() => { |
| it('should return mean with weight', () => { |
| assert.equal(Statistics.weightedMean([{value: 1, weight: 1}, {value: 2, weight: 2}, |
| {value: 3, weight: 3}, {value: 4, weight: 4}]), 3); |
| assert.equal(Statistics.weightedMean([{value: 1, weight: 1}, {value: 2, weight: 0}, |
| {value: 3, weight: 0}, {value: 4, weight: 0}]), 1); |
| }); |
| }); |
| |
| describe('squareSum', function () { |
| it('should find the square sum of values', function () { |
| assert.equal(Statistics.squareSum([1, 2, 3, 4]), 30); |
| assert.equal(Statistics.squareSum([4, 3, 2, 1]), 30); |
| assert.equal(Statistics.squareSum([2000, 20, 200]), 2000 * 2000 + 20 * 20 + 200* 200); |
| assert.equal(Statistics.squareSum([0.3, 0.06, 0.5]), 0.09 + 0.0036 + 0.25); |
| assert.equal(Statistics.squareSum([-0.3, 0.06, 0.5]), 0.09 + 0.0036 + 0.25); |
| assert.equal(Statistics.squareSum([-0.3, 0.06, 0.5, Infinity]), Infinity); |
| assert.equal(Statistics.squareSum([-0.3, 0.06, 0.5, -Infinity]), Infinity); |
| assert.equal(Statistics.squareSum([]), 0); |
| }); |
| }); |
| |
| describe('sampleStandardDeviation', function () { |
| function stdev(values) { |
| return Statistics.sampleStandardDeviation(values.length, |
| Statistics.sum(values), Statistics.squareSum(values)); |
| } |
| |
| it('should find the standard deviation of values', function () { |
| assert.almostEqual(stdev([1, 2, 3, 4]), 1.2909944); |
| assert.almostEqual(stdev([4, 3, 2, 1]), 1.2909944); |
| assert.almostEqual(stdev([2000, 20, 200]), 1094.89726); |
| assert.almostEqual(stdev([0.3, 0.06, 0.5]), 0.220302822); |
| assert.almostEqual(stdev([-0.3, 0.06, 0.5]), 0.40066611203); |
| assert.almostEqual(stdev([-0.3, 0.06, 0.5, Infinity]), NaN); |
| assert.almostEqual(stdev([-0.3, 0.06, 0.5, -Infinity]), NaN); |
| assert.almostEqual(stdev([]), 0); |
| }); |
| }); |
| |
| describe('confidenceIntervalDelta', function () { |
| it('should find the p-value of values using Student\'s t distribution', function () { |
| function delta(values, probabilty) { |
| return Statistics.confidenceIntervalDelta(probabilty, values.length, |
| Statistics.sum(values), Statistics.squareSum(values)); |
| } |
| |
| // https://onlinecourses.science.psu.edu/stat414/node/199 |
| var values = [118, 115, 125, 110, 112, 130, 117, 112, 115, 120, 113, 118, 119, 122, 123, 126]; |
| assert.almostEqual(delta(values, 0.95), 3.015, 3); |
| |
| // Following values are computed using Excel Online's STDEV and CONFIDENCE.T |
| assert.almostEqual(delta([1, 2, 3, 4], 0.8), 1.057159, 4); |
| assert.almostEqual(delta([1, 2, 3, 4], 0.9), 1.519090, 4); |
| assert.almostEqual(delta([1, 2, 3, 4], 0.95), 2.054260, 4); |
| |
| assert.almostEqual(delta([0.3, 0.06, 0.5], 0.8), 0.2398353, 4); |
| assert.almostEqual(delta([0.3, 0.06, 0.5], 0.9), 0.3713985, 4); |
| assert.almostEqual(delta([0.3, 0.06, 0.5], 0.95), 0.5472625, 4); |
| |
| assert.almostEqual(delta([-0.3, 0.06, 0.5], 0.8), 0.4361900, 4); |
| assert.almostEqual(delta([-0.3, 0.06, 0.5], 0.9), 0.6754647, 4); |
| assert.almostEqual(delta([-0.3, 0.06, 0.5], 0.95), 0.9953098, 4); |
| |
| assert.almostEqual(delta([123, 107, 109, 104, 111], 0.8), 5.001167, 4); |
| assert.almostEqual(delta([123, 107, 109, 104, 111], 0.9), 6.953874, 4); |
| assert.almostEqual(delta([123, 107, 109, 104, 111], 0.95), 9.056490, 4); |
| |
| assert.almostEqual(delta([6785, 7812, 6904, 7503, 6943, 7207, 6812], 0.8), 212.6155, 4); |
| assert.almostEqual(delta([6785, 7812, 6904, 7503, 6943, 7207, 6812], 0.9), 286.9585, 4); |
| assert.almostEqual(delta([6785, 7812, 6904, 7503, 6943, 7207, 6812], 0.95), 361.3469, 4); |
| |
| }); |
| }); |
| |
| // https://en.wikipedia.org/wiki/Welch%27s_t_test |
| |
| var example1 = { |
| A1: [27.5, 21.0, 19.0, 23.6, 17.0, 17.9, 16.9, 20.1, 21.9, 22.6, 23.1, 19.6, 19.0, 21.7, 21.4], |
| A2: [27.1, 22.0, 20.8, 23.4, 23.4, 23.5, 25.8, 22.0, 24.8, 20.2, 21.9, 22.1, 22.9, 20.5, 24.4], |
| expectedT: 2.46, |
| expectedDegreesOfFreedom: 25.0, |
| expectedRange: [0.95, 0.98] // P = 0.021 so 1 - P = 0.979 is between 0.95 and 0.98 |
| }; |
| |
| var example2 = { |
| A1: [17.2, 20.9, 22.6, 18.1, 21.7, 21.4, 23.5, 24.2, 14.7, 21.8], |
| A2: [21.5, 22.8, 21.0, 23.0, 21.6, 23.6, 22.5, 20.7, 23.4, 21.8, 20.7, 21.7, 21.5, 22.5, 23.6, 21.5, 22.5, 23.5, 21.5, 21.8], |
| expectedT: 1.57, |
| expectedDegreesOfFreedom: 9.9, |
| expectedRange: [0.8, 0.9] // P = 0.149 so 1 - P = 0.851 is between 0.8 and 0.9 |
| }; |
| |
| var example3 = { |
| A1: [19.8, 20.4, 19.6, 17.8, 18.5, 18.9, 18.3, 18.9, 19.5, 22.0], |
| A2: [28.2, 26.6, 20.1, 23.3, 25.2, 22.1, 17.7, 27.6, 20.6, 13.7, 23.2, 17.5, 20.6, 18.0, 23.9, 21.6, 24.3, 20.4, 24.0, 13.2], |
| expectedT: 2.22, |
| expectedDegreesOfFreedom: 24.5, |
| expectedRange: [0.95, 0.98] // P = 0.036 so 1 - P = 0.964 is beteween 0.95 and 0.98 |
| }; |
| |
| describe('computeWelchsT', function () { |
| function computeWelchsT(values1, values2, probability) { |
| return Statistics.computeWelchsT(values1, 0, values1.length, values2, 0, values2.length, probability); |
| } |
| |
| it('should detect the statistically significant difference using Welch\'s t-test', function () { |
| assert.equal(computeWelchsT(example1.A1, example1.A2, 0.8).significantlyDifferent, true); |
| assert.equal(computeWelchsT(example1.A1, example1.A2, 0.9).significantlyDifferent, true); |
| assert.equal(computeWelchsT(example1.A1, example1.A2, 0.95).significantlyDifferent, true); |
| assert.equal(computeWelchsT(example1.A1, example1.A2, 0.98).significantlyDifferent, false); |
| |
| assert.equal(computeWelchsT(example2.A1, example2.A2, 0.8).significantlyDifferent, true); |
| assert.equal(computeWelchsT(example2.A1, example2.A2, 0.9).significantlyDifferent, false); |
| assert.equal(computeWelchsT(example2.A1, example2.A2, 0.95).significantlyDifferent, false); |
| assert.equal(computeWelchsT(example2.A1, example2.A2, 0.98).significantlyDifferent, false); |
| |
| assert.equal(computeWelchsT(example3.A1, example3.A2, 0.8).significantlyDifferent, true); |
| assert.equal(computeWelchsT(example3.A1, example3.A2, 0.9).significantlyDifferent, true); |
| assert.equal(computeWelchsT(example3.A1, example3.A2, 0.95).significantlyDifferent, true); |
| assert.equal(computeWelchsT(example3.A1, example3.A2, 0.98).significantlyDifferent, false); |
| }); |
| |
| it('should find the t-value of values using Welch\'s t-test', function () { |
| assert.almostEqual(computeWelchsT(example1.A1, example1.A2).t, example1.expectedT, 2); |
| assert.almostEqual(computeWelchsT(example2.A1, example2.A2).t, example2.expectedT, 2); |
| assert.almostEqual(computeWelchsT(example3.A1, example3.A2).t, example3.expectedT, 2); |
| }); |
| |
| it('should find the degreees of freedom using Welch–Satterthwaite equation', function () { |
| assert.almostEqual(computeWelchsT(example1.A1, example1.A2).degreesOfFreedom, example1.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(computeWelchsT(example2.A1, example2.A2).degreesOfFreedom, example2.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(computeWelchsT(example3.A1, example3.A2).degreesOfFreedom, example3.expectedDegreesOfFreedom, 2); |
| }); |
| |
| it('should respect the start and the end indices', function () { |
| var A1 = example2.A1.slice(); |
| var A2 = example2.A2.slice(); |
| |
| var expectedT = Statistics.computeWelchsT(A1, 0, A1.length, A2, 0, A2.length).t; |
| |
| A1.unshift(21); |
| A1.push(15); |
| A1.push(24); |
| assert.almostEqual(Statistics.computeWelchsT(A1, 1, A1.length - 3, A2, 0, A2.length).t, expectedT); |
| |
| A2.unshift(24.3); |
| A2.unshift(25.8); |
| A2.push(23); |
| A2.push(24); |
| A2 = A2.reverse(); |
| assert.almostEqual(Statistics.computeWelchsT(A1, 1, A1.length - 3, A2, 2, A2.length - 4).t, expectedT); |
| }); |
| }); |
| |
| describe('probabilityRangeForWelchsT', function () { |
| it('should find the t-value of values using Welch\'s t-test', function () { |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).t, example1.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).t, example2.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).t, example3.expectedT, 2); |
| }); |
| |
| it('should find the degreees of freedom using Welch–Satterthwaite equation', function () { |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).degreesOfFreedom, |
| example1.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).degreesOfFreedom, |
| example2.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).degreesOfFreedom, |
| example3.expectedDegreesOfFreedom, 2); |
| }); |
| |
| it('should compute the range of probabilites using the p-value of Welch\'s t-test', function () { |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).range[0], example1.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).range[1], example1.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).range[0], example2.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).range[1], example2.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).range[0], example3.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).range[1], example3.expectedRange[1]); |
| }); |
| }); |
| |
| describe('minimumTForOneSidedProbability', () => { |
| it('should not infinite loop when lookup t-value for any degrees of freedom', () => { |
| for(const probability of [0.9, 0.95, 0.975, 0.99]) { |
| for (let degreesOfFreedom = 1; degreesOfFreedom < 100000; degreesOfFreedom += 1) |
| Statistics.minimumTForOneSidedProbability(probability, degreesOfFreedom); |
| } |
| }) |
| }); |
| |
| describe('probabilityRangeForWelchsTForMultipleSamples', () => { |
| function splitSample(samples) { |
| const mid = samples.length / 2; |
| return splitSampleByIndices(samples, mid); |
| } |
| |
| function splitSampleByIndices(samples, ...indices) { |
| const sampleSize = samples.length; |
| const splittedSamples = []; |
| let previousIndex = 0; |
| for (const index of indices) { |
| if (index == previousIndex) |
| continue; |
| console.assert(index > previousIndex); |
| console.assert(index <= sampleSize); |
| splittedSamples.push(samples.slice(previousIndex, index)); |
| previousIndex = index; |
| } |
| if (previousIndex < sampleSize) |
| splittedSamples.push(samples.slice(previousIndex, sampleSize)); |
| return splittedSamples.map((values) => ({sum: Statistics.sum(values), squareSum: Statistics.squareSum(values), sampleSize: values.length})); |
| } |
| |
| it('should find the t-value of values using Welch\'s t-test', () => { |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).t, example1.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).t, example2.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).t, example3.expectedT, 2); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).t, example1.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).t, example2.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).t, example3.expectedT, 2); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).t, example1.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).t, example2.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).t, example3.expectedT, 2); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).t, example1.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).t, example2.expectedT, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).t, example3.expectedT, 2); |
| }); |
| |
| it('should find the degreees of freedom using Welch–Satterthwaite equation when split evenly', () => { |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).degreesOfFreedom, |
| example1.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).degreesOfFreedom, |
| example2.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).degreesOfFreedom, |
| example3.expectedDegreesOfFreedom, 2); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).degreesOfFreedom, |
| example1.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).degreesOfFreedom, |
| example2.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).degreesOfFreedom, |
| example3.expectedDegreesOfFreedom, 2); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).degreesOfFreedom, |
| example1.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).degreesOfFreedom, |
| example2.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).degreesOfFreedom, |
| example3.expectedDegreesOfFreedom, 2); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).degreesOfFreedom, |
| example1.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).degreesOfFreedom, |
| example2.expectedDegreesOfFreedom, 2); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).degreesOfFreedom, |
| example3.expectedDegreesOfFreedom, 2); |
| }); |
| |
| it('should compute the range of probabilites using the p-value of Welch\'s t-test when split evenly', function () { |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).range[0], example1.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).range[1], example1.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).range[0], example2.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).range[1], example2.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).range[0], example3.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).range[1], example3.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).range[0], example1.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).range[1], example1.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).range[0], example2.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).range[1], example2.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).range[0], example3.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).range[1], example3.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).range[0], example1.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).range[1], example1.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).range[0], example2.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).range[1], example2.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).range[0], example3.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).range[1], example3.expectedRange[1]); |
| |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).range[0], example1.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).range[1], example1.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).range[0], example2.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).range[1], example2.expectedRange[1]); |
| |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).range[0], example3.expectedRange[0]); |
| assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).range[1], example3.expectedRange[1]); |
| |
| }); |
| }); |
| |
| describe('movingAverage', function () { |
| it('should return the origian values when both forward and backward window size is 0', function () { |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 0), [1, 2, 3, 4, 5]); |
| }); |
| |
| it('should find the moving average with a positive backward window', function () { |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 1, 0), |
| [1, (1 + 2) / 2, (2 + 3) / 2, (3 + 4) / 2, (4 + 5) / 2]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 0), |
| [1, (1 + 2) / 2, (1 + 2 + 3) / 3, (2 + 3 + 4) / 3, (3 + 4 + 5) / 3]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 3, 0), |
| [1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 4, 0), |
| [1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 5, 0), |
| [1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5]); |
| }); |
| |
| it('should find the moving average with a positive forward window', function () { |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 1), |
| [(1 + 2) / 2, (2 + 3) / 2, (3 + 4) / 2, (4 + 5) / 2, 5]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 2), |
| [(1 + 2 + 3) / 3, (2 + 3 + 4) / 3, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 3), |
| [(1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 4), |
| [(1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 5), |
| [(1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]); |
| }); |
| |
| it('should find the moving average when both backward and forward window sizes are specified', function () { |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 1, 1), |
| [(1 + 2) / 2, (1 + 2 + 3) / 3, (2 + 3 + 4) / 3, (3 + 4 + 5) / 3, (4 + 5) / 2]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 1, 2), |
| [(1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 1), |
| [(1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 2), |
| [(1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 3), |
| [(1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 3, 2), |
| [(1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4]); |
| |
| assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 3, 3), |
| [(1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4]); |
| }); |
| }); |
| |
| describe('cumulativeMovingAverage', function () { |
| it('should find the cumulative moving average', function () { |
| assert.deepEqual(Statistics.cumulativeMovingAverage([1, 2, 3, 4, 5]), |
| [1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5]); |
| |
| assert.deepEqual(Statistics.cumulativeMovingAverage([-1, 7, 0, 8.5, 2]), |
| [-1, (-1 + 7) / 2, (-1 + 7 + 0) / 3, (-1 + 7 + 0 + 8.5) / 4, (-1 + 7 + 0 + 8.5 + 2) / 5]); |
| }); |
| }); |
| |
| describe('exponentialMovingAverage', function () { |
| it('should find the exponential moving average', function () { |
| var averages = Statistics.exponentialMovingAverage([1, 2, 3, 4, 5], 0.2); |
| assert.equal(averages[0], 1); |
| assert.almostEqual(averages[1], 0.2 * 2 + 0.8 * averages[0]); |
| assert.almostEqual(averages[2], 0.2 * 3 + 0.8 * averages[1]); |
| assert.almostEqual(averages[3], 0.2 * 4 + 0.8 * averages[2]); |
| assert.almostEqual(averages[4], 0.2 * 5 + 0.8 * averages[3]); |
| |
| averages = Statistics.exponentialMovingAverage([0.8, -0.2, 0.4, -0.3, 0.5], 0.1); |
| assert.almostEqual(averages[0], 0.8); |
| assert.almostEqual(averages[1], 0.1 * -0.2 + 0.9 * averages[0]); |
| assert.almostEqual(averages[2], 0.1 * 0.4 + 0.9 * averages[1]); |
| assert.almostEqual(averages[3], 0.1 * -0.3 + 0.9 * averages[2]); |
| assert.almostEqual(averages[4], 0.1 * 0.5 + 0.9 * averages[3]); |
| }); |
| }); |
| |
| describe('segmentTimeSeriesGreedyWithStudentsTTest', function () { |
| it('should segment time series', function () { |
| assert.deepEqual(Statistics.segmentTimeSeriesGreedyWithStudentsTTest([1, 1, 1, 3, 3, 3], 1), [0, 2, 6]); |
| assert.deepEqual(Statistics.segmentTimeSeriesGreedyWithStudentsTTest([1, 1.2, 0.9, 1.1, 1.5, 1.7, 1.8], 1), [0, 4, 7]); |
| }); |
| }); |
| |
| describe('segmentTimeSeriesByMaximizingSchwarzCriterion', function () { |
| it('should segment time series of length 0 into a single segment', function () { |
| var values = []; |
| assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 0]); |
| }); |
| |
| it('should not segment time series of length two into two pieces', function () { |
| var values = [1, 2]; |
| assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 2]); |
| }); |
| |
| it('should segment time series [1, 2, 3] into three pieces', function () { |
| var values = [1, 2, 3]; |
| assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 1, 3]); |
| }); |
| |
| it('should segment time series for platform=47 metric=4875 between 1453938553772 and 1454630903100 into two parts', function () { |
| var values = [ |
| 1546.5603, 1548.1536, 1563.5452, 1539.7823, 1546.4184, 1548.9299, 1532.5444, 1546.2800, 1547.1760, 1551.3507, |
| 1548.3277, 1544.7673, 1542.7157, 1538.1700, 1538.0948, 1543.0364, 1537.9737, 1542.2611, 1543.9685, 1546.4901, |
| 1544.4080, 1540.8671, 1537.3353, 1549.4331, 1541.4436, 1544.1299, 1550.1770, 1553.1872, 1549.3417, 1542.3788, |
| 1543.5094, 1541.7905, 1537.6625, 1547.3840, 1538.5185, 1549.6764, 1556.6138, 1552.0476, 1541.7629, 1544.7006, |
| /* segments changes here */ |
| 1587.1390, 1594.5451, 1586.2430, 1596.7310, 1548.1423]; |
| assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 39, values.length]); |
| }); |
| |
| it('should segment time series for platform=51 metric=4565 betweeen 1452191332230 and 1454628206453 into two parts', function () { |
| var values = [ |
| 147243216, 147736350, 146670090, 146629723, 142749220, 148234161, 147303822, 145112097, 145852468, 147094741, |
| 147568897, 145160531, 148028242, 141272279, 144323236, 147492567, 146219156, 144895726, 144418925, 145455873, |
| 141924694, 141025833, 142082139, 144154698, 145312939, 148282554, 151852126, 149303740, 149431703, 150300257, |
| 148752468, 150449779, 150030118, 150553542, 151775421, 146666762, 149492535, 147143284, 150356837, 147799616, |
| 149889520, |
| 258634751, 147397840, 256106147, 261100534, 255903392, 259658019, 259501433, 257685682, 258460322, 255563633, |
| 259050663, 255567490, 253274911]; |
| assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 40, values.length]); |
| }); |
| |
| it('should not segment time series for platform=51 metric=4817 betweeen 1453926047749 and 1454635479052 into multiple parts', function () { |
| var values = [ |
| 5761.3, 5729.4, 5733.49, 5727.4, 5726.56, 5727.48, 5716.79, 5721.23, 5682.5, 5735.71, |
| 5750.99, 5755.51, 5756.02, 5725.76, 5710.14, 5776.17, 5774.29, 5769.99, 5739.65, 5756.05, |
| 5722.87, 5726.8, 5779.23, 5772.2, 5763.1, 5807.05]; |
| assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, values.length]); |
| }); |
| |
| it('should not segment time series for platform=51 metric=4817 betweeen 1453926047749 and 1454635479052 into multiple parts', function () { |
| var values = new Array(37); |
| for (let i = 0; i < 37; i++) |
| values[i] = 1; |
| assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [ 0, 6, 16, 26, 37 ]); |
| }); |
| }); |
| |
| describe('findRangesForChangeDetectionsWithWelchsTTest', () => { |
| it('should return an empty array if the value is empty list', () => { |
| assert.deepEqual(Statistics.findRangesForChangeDetectionsWithWelchsTTest([], [], 0.975), []); |
| }); |
| |
| it('should return an empty array if segmentation is empty list', () => { |
| assert.deepEqual(Statistics.findRangesForChangeDetectionsWithWelchsTTest([1,2,3], [], 0.975), []); |
| }); |
| |
| it('should return the range if computeWelchsT shows a significant change', () => { |
| const values = [ |
| 747.30337423744, |
| 731.47392585276, |
| 743.66763513161, |
| 738.02055323487, |
| 738.25426340842, |
| 742.38680046471, |
| 733.13921703284, |
| 739.22069966147, |
| 735.69295749633, |
| 743.01705472504, |
| 745.45778145306, |
| 731.04841157169, |
| 729.4372674973, |
| 735.4497416527, |
| 739.0230668644, |
| 730.91782989909, |
| 722.18725411279, |
| 731.96223451728, |
| 730.04119216192, |
| 730.78087646284, |
| 729.63155210365, |
| 730.17585200878, |
| 733.93766054706, |
| 740.74920717197, |
| 752.14718023647, |
| 764.49990164847, |
| 766.36100828473, |
| 756.2291883252, |
| 750.14522451097, |
| 749.57595092266, |
| 748.03624881866, |
| 769.41522176386, |
| 744.04660430456, |
| 751.17927808265, |
| 753.29996854062, |
| 757.01813756936, |
| 746.62413820741, |
| 742.64420062736, |
| 758.12726352772, |
| 778.2278439089, |
| 775.11818554541, |
| 775.11818554541]; |
| const segmentation = [{ |
| seriesIndex: 0, |
| time: 1505176030671, |
| value: 736.5366704896555, |
| x: 370.4571789404566, |
| y: 185.52613334520248, |
| }, |
| { |
| seriesIndex: 18, |
| time: 1515074391534, |
| value: 736.5366704896555, |
| x: 919.4183852714947, |
| y: 185.52613334520248 |
| }, |
| { |
| seriesIndex: 18, |
| time: 1515074391534, |
| value: 750.3483428383142, |
| x: 919.4183852714947, |
| y: 177.9710953409673, |
| }, |
| { |
| seriesIndex: 41, |
| time: 1553851695869, |
| value: 750.3483428383142, |
| x: 3070.000290764446, |
| y: 177.9710953409673, |
| }]; |
| assert.deepEqual(Statistics.findRangesForChangeDetectionsWithWelchsTTest(values, segmentation, 0.975), [ |
| { |
| "endIndex": 29, |
| "segmentationEndValue": 750.3483428383142, |
| "segmentationStartValue": 736.5366704896555, |
| "startIndex": 6 |
| } |
| ]); |
| }) |
| }); |
| }); |