Skip to content

Commit fb91879

Browse files
feat: add mean absolute deviation algorithm
1 parent 5c39e87 commit fb91879

2 files changed

Lines changed: 53 additions & 22 deletions

File tree

‎Maths/MeanAbsoluteDeviation.js‎

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
import { mean } from './AverageMean.js'
21
/**
3-
*@function meanAbsoluteDeviation
4-
*@description Calculates the mean absolute deviation of list of numbers
5-
* @param {Integer} data
6-
* @returns meanAbsoluteDeviation([2,34,5,0,-2]) = 10.480
7-
* @url https://en.wikipedia.org/wiki/Average_absolute_deviation
2+
* @function meanAbsoluteDeviation
3+
* @description Calculates the mean absolute deviation (MAD) of an array
4+
* of numbers. MAD is the average of the absolute differences between
5+
* each value and the mean of the dataset.
6+
* @param {number[]} arr - An array of numbers
7+
* @returns {number} - The mean absolute deviation
8+
* @see https://en.wikipedia.org/wiki/Average_absolute_deviation
9+
* @example meanAbsoluteDeviation([2, 2, 3, 4, 14]) => 3.6
10+
* @example meanAbsoluteDeviation([1, 1, 1]) => 0
811
*/
9-
function meanAbsoluteDeviation(data) {
10-
if (!Array.isArray(data)) {
11-
throw new TypeError('Invalid Input')
12+
const meanAbsoluteDeviation = (arr) => {
13+
if (!Array.isArray(arr) || arr.length === 0) {
14+
throw new TypeError('Input must be a non-empty array')
1215
}
13-
let absoluteSum = 0
14-
const meanValue = mean(data)
15-
for (const dataPoint of data) {
16-
absoluteSum += Math.abs(dataPoint - meanValue)
16+
if (!arr.every((n) => typeof n === 'number' && !isNaN(n))) {
17+
throw new TypeError('All elements must be numbers')
1718
}
18-
return absoluteSum / data.length
19+
const mean = arr.reduce((sum, n) => sum + n, 0) / arr.length
20+
return arr.reduce((sum, n) => sum + Math.abs(n - mean), 0) / arr.length
1921
}
2022

2123
export { meanAbsoluteDeviation }
Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,45 @@
11
import { meanAbsoluteDeviation } from '../MeanAbsoluteDeviation.js'
22

3-
describe('tests for mean absolute deviation', () => {
4-
it('should be a function', () => {
5-
expect(typeof meanAbsoluteDeviation).toEqual('function')
3+
describe('meanAbsoluteDeviation', () => {
4+
test('meanAbsoluteDeviation([2,2,3,4,14]) returns 3.6', () => {
5+
expect(meanAbsoluteDeviation([2, 2, 3, 4, 14])).toBeCloseTo(3.6)
66
})
77

8-
it('should throw an invalid input error', () => {
9-
expect(() => meanAbsoluteDeviation('fgh')).toThrow()
8+
test('meanAbsoluteDeviation([1,1,1]) returns 0', () => {
9+
expect(meanAbsoluteDeviation([1, 1, 1])).toBe(0)
1010
})
1111

12-
it('should return the mean absolute deviation of an array of numbers', () => {
13-
const meanAbDev = meanAbsoluteDeviation([2, 34, 5, 0, -2])
14-
expect(meanAbDev).toBe(10.479999999999999)
12+
test('meanAbsoluteDeviation single element returns 0', () => {
13+
expect(meanAbsoluteDeviation([5])).toBe(0)
14+
})
15+
16+
test('meanAbsoluteDeviation([1,2,3,4,5]) returns 1.2', () => {
17+
expect(meanAbsoluteDeviation([1, 2, 3, 4, 5])).toBeCloseTo(1.2)
18+
})
19+
20+
test('meanAbsoluteDeviation works with negative numbers', () => {
21+
expect(meanAbsoluteDeviation([-2, -1, 0, 1, 2])).toBeCloseTo(1.2)
22+
})
23+
24+
test('meanAbsoluteDeviation([10, 20]) returns 5', () => {
25+
expect(meanAbsoluteDeviation([10, 20])).toBeCloseTo(5)
26+
})
27+
28+
test('meanAbsoluteDeviation does not mutate original array', () => {
29+
const arr = [1, 2, 3, 4, 5]
30+
meanAbsoluteDeviation(arr)
31+
expect(arr).toEqual([1, 2, 3, 4, 5])
32+
})
33+
34+
test('throws TypeError for empty array', () => {
35+
expect(() => meanAbsoluteDeviation([])).toThrow(TypeError)
36+
})
37+
38+
test('throws TypeError for non-array input', () => {
39+
expect(() => meanAbsoluteDeviation('123')).toThrow(TypeError)
40+
})
41+
42+
test('throws TypeError for array with non-numbers', () => {
43+
expect(() => meanAbsoluteDeviation([1, 'two', 3])).toThrow(TypeError)
1544
})
1645
})

0 commit comments

Comments
 (0)