Permalink
Browse files

Merge pull request #763 from ruhleder/feature/median-absolute-deviation

Add median absolute deviation
  • Loading branch information...
2 parents a5df5e4 + fe52d51 commit b39612bf14950e3c380807233a1060e111643947 @josdejong committed on GitHub Dec 10, 2016
Showing with 126 additions and 1 deletion.
  1. +2 −1 lib/function/statistics/index.js
  2. +64 −0 lib/function/statistics/mad.js
  3. +60 −0 test/function/statistics/mad.test.js
@@ -1,4 +1,5 @@
module.exports = [
+ require('./mad'),
require('./max'),
require('./mean'),
require('./median'),
@@ -9,4 +10,4 @@ module.exports = [
require('./std'),
require('./sum'),
require('./var')
-];
+];
@@ -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;
@@ -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.