diff --git a/README.md b/README.md index 7622f26..0031827 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ npm i stat-methods - [pStdev](#pStdev) - [variance](#variance) - [stdev](#stdev) + - [medAbsdev](#medAbsdev) - [range](#range) 3. [Descriptive statistics](#Descriptive-statistics) @@ -332,6 +333,7 @@ These methods compute a measure of the variability in a sample or population, ho - [pStdev](#pStdev): Population standard deviation - [variance](#variance): Sample variance - [stdev](#stdev): Sample standard deviation +- [medAbsdev](#medAbsdev): Median absolute deviation - [range](#range): Range #### pVariance @@ -430,6 +432,22 @@ stdev([1, 2, 3, 4, 5], xBar); // -> 1.5811388300841898 Please refer to the [variance](#variance) method for further details. +#### medAbsdev + +```js +medAbsdev(arr); +``` + +Return the median absolute deviation of a numeric data array `arr`. + +The median absolute deviation is the median of the absolute deviations from a data sample's median. + +```js +medAbsdev([1, 2, 3, 4, 5]); // -> 1 +``` + +If the data array is empty or contains a non finite `Number`, the method returns `undefined`. + #### range ```js diff --git a/src/spread.js b/src/spread.js index 65acbec..0fb7e7a 100644 --- a/src/spread.js +++ b/src/spread.js @@ -1,4 +1,8 @@ -import { mean } from './central'; +import { + mean, + median, +} from './central'; + import { min, max, @@ -81,6 +85,24 @@ export function stdev(arr, xBar) { return v === undefined ? v : Math.sqrt(v); } +/** + * Return the median absolute deviation of a numeric data array. + * The median absolute deviation is the median of the absolute deviations + * from a data sample's median. + * @param {Number[]} arr the data array + * @returns {Number} the median absolute deviation of the data array + */ +export function medAbsdev(arr) { + const med = median(arr); + const absoluteDeviationArr = []; + if (med === undefined) return undefined; + for (let i = 0; i < arr.length; i += 1) { + const absdev = Math.abs(arr[i] - med); + absoluteDeviationArr.push(absdev); + } + return median(absoluteDeviationArr); +} + /** * Return the range of a numeric data array. * The range of a set of data is the difference between the largest and smallest values. @@ -99,5 +121,6 @@ export default { pStdev, variance, stdev, + medAbsdev, range, }; diff --git a/test/spread.test.js b/test/spread.test.js index 1e7ce78..f191ac4 100644 --- a/test/spread.test.js +++ b/test/spread.test.js @@ -4,6 +4,7 @@ import { pStdev, variance, stdev, + medAbsdev, range, } from '../src/spread'; @@ -53,6 +54,19 @@ describe('Measures of spread', () => { testUndefinedWithNullable(stdev); }); + test('Median Absolute Deviation', () => { + expect(medAbsdev([1, 12, 3, 15, 6, 8, 9])).toBe(4); + expect(medAbsdev([1, -2, 3, 4, 8, 6, 5, 9])).toBe(2.5); + expect(medAbsdev([1, 2, 3, 4, 5])).toBe(1); + expect(medAbsdev([1, 2, 3, 4, 5, 6])).toBe(1.5); + expect(medAbsdev(['a', 2.5, 'b', 5.75])).toBeUndefined(); + expect(medAbsdev([NaN, 2.5, 3, 5.75])).toBeUndefined(); + expect(medAbsdev([])).toBeUndefined(); + expect(medAbsdev(3)).toBeUndefined(); + expect(medAbsdev([3])).toBe(0); + testUndefinedWithNullable(medAbsdev); + }); + test('Range', () => { expect(range([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])).toBe(3.25); expect(range([89, 73, 84, 91, 87, 77, 94])).toBe(21);