Skip to content

Commit

Permalink
Merge pull request #763 from ruhleder/feature/median-absolute-deviation
Browse files Browse the repository at this point in the history
Add median absolute deviation
  • Loading branch information
josdejong committed Dec 10, 2016
2 parents a5df5e4 + fe52d51 commit b39612b
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/function/statistics/index.js
@@ -1,4 +1,5 @@
module.exports = [
require('./mad'),
require('./max'),
require('./mean'),
require('./median'),
Expand All @@ -9,4 +10,4 @@ module.exports = [
require('./std'),
require('./sum'),
require('./var')
];
];
64 changes: 64 additions & 0 deletions lib/function/statistics/mad.js
@@ -0,0 +1,64 @@
'use strict';

var flatten = require('../../utils/array').flatten;

function factory (type, config, load, typed) {
var abs = load(require('../arithmetic/abs'));
var map = load(require('../matrix/map'));
var median = load(require('../statistics/median'));
var subtract = load(require('../arithmetic/subtract'));

/**
* Compute the median absolute deviation of a matrix or a list with values.
* The median absolute deviation is defined as the median of the absolute
* deviations from the median.
*
* Syntax:
*
* math.mad(a, b, c, ...)
* math.mad(A)
*
* Examples:
*
* math.mad(10, 20, 30); // returns 10
* math.mad([1, 2, 3]); // returns 1
* math.mad([[1, 2, 3], [4, 5, 6]]); // returns 1.5
*
* See also:
*
* median, abs, map, subtract
*
* @param {Array | Matrix} array
* A single matrix or multiple scalar values.
* @return {*} The median absolute deviation.
*/
var mad = typed('mad', {
// mad([a, b, c, d, ...])
'Array | Matrix': _mad,

// mad(a, b, c, d, ...)
'...': function (args) {
return _mad(args);
}
});

mad.toTex = undefined; // use default template

return mad;

function _mad(array) {
array = flatten(array.valueOf());

if (array.length === 0) {
throw new Error('Cannot calculate median absolute deviation of an empty array');
}

var med = median(array);
return median(map(array, function (value) {
return abs(subtract(value, med));
}));
}
}

exports.name = 'mad';
exports.factory = factory;
60 changes: 60 additions & 0 deletions test/function/statistics/mad.test.js
@@ -0,0 +1,60 @@
var assert = require('assert');
var approx = require('../../../tools/approx');
var math = require('../../../index');
var BigNumber = math.type.BigNumber;
var DenseMatrix = math.type.DenseMatrix;
var mad = math.mad;

describe('mad', function() {

it('should return the median absolute deviation of numbers', function() {
assert.equal(mad(10), 0);
assert.equal(mad(4,6,8), 2);
assert.equal(mad(1, 10, 20, 30), 9.5);
});

it('should return the median absolute deviation of big numbers', function() {
assert.deepEqual(mad(new BigNumber(4),new BigNumber(6),new BigNumber(8)),
new BigNumber(2));
});

it('should return the median absolute deviation from an array', function() {
assert.equal(mad([10]), 0);
assert.equal(mad([4,6,8]), 2);
assert.equal(mad([1, 10, 20, 30]), 9.5);
});

it('should return the median absolute deviation from an 1d matrix', function() {
assert.equal(mad(new DenseMatrix([10])), 0);
assert.equal(mad(new DenseMatrix([4,6,8])), 2);
assert.equal(mad(new DenseMatrix([1, 10, 20, 30])), 9.5);
});

it('should return the median absolute deviation element from a 2d array', function() {
assert.deepEqual(mad([
[2,4,6],
[1,3,5]
]), 1.5);
});

it('should return the median absolute deviation element from a 2d matrix', function() {
assert.deepEqual(mad(new DenseMatrix([
[2,4,6],
[1,3,5]
])), 1.5);
});

it('should throw an error if called with invalid number of arguments', function() {
assert.throws(function() {mad()});
});

it('should throw an error if called with an empty array', function() {
assert.throws(function() {mad([])});
});

it('should LaTeX mad', function () {
var expression = math.parse('mad(1,2,3)');
assert.equal(expression.toTex(), '\\mathrm{mad}\\left(1,2,3\\right)');
});

});

0 comments on commit b39612b

Please sign in to comment.