I am trying to get the standard deviation of a user input string. I have as follows, but it returns the wrong value for SD. The calculation should go as follows: Sum values/
This ES6 implementation matches Excel's built in STDEV.P
and STDEV.S
(.S
is the default when STDEV
is called). Passing in the true
flag for usePopulation
here will match Excel's STDEV.P
const standardDeviation = (arr, usePopulation = false) => {
const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
return Math.sqrt(
arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) /
(arr.length - (usePopulation ? 0 : 1))
);
};
console.log('STDEV.S =>',
standardDeviation([
10, 2, 38, 23, 38, 23, 21
])
);
console.log('STDEV.P =>',
standardDeviation([
10, 2, 38, 23, 38, 23, 21
], true)
);
Original Source
Quick implementation of the standard deviation function:
const sd = numbers => {
const mean = numbers.reduce((acc, n) => acc + n) / numbers.length;
return Math.sqrt(
numbers.reduce((acc, n) => (n - mean) ** 2) / numbers.length
);
};
Corrected SD version:
const correctedSd = numbers => {
const mean = numbers.reduce((acc, n) => acc + n) / numbers.length;
return Math.sqrt(
numbers.reduce((acc, n) => (n - mean) ** 2) / (numbers.length - 1)
);
};
function StandardDeviation(numbersArr) {
//--CALCULATE AVAREGE--
var total = 0;
for(var key in numbersArr)
total += numbersArr[key];
var meanVal = total / numbersArr.length;
//--CALCULATE AVAREGE--
//--CALCULATE STANDARD DEVIATION--
var SDprep = 0;
for(var key in numbersArr)
SDprep += Math.pow((parseFloat(numbersArr[key]) - meanVal),2);
var SDresult = Math.sqrt(SDprep/numbersArr.length);
//--CALCULATE STANDARD DEVIATION--
alert(SDresult);
}
var numbersArr = [10, 11, 12, 13, 14];
StandardDeviation(numbersArr);
I think the (main) problem is on this line:
v1 = parseFloat(Math.pow(temp[i]-mean),2);
Should be:
v1 = Math.pow(parseFloat(temp[i])-mean),2);
Your code is trying to use the string in temp[i]
as a number and subtract mean
from it, and then square it, and then parse the resulting value. Need to parseFloat before using it in a calculation. Also you've got the ,2
outside the closing parenenthesis for the Math.pow
call so the squaring won't work either.
Would be helpful to use more meaningful variable names too, I mean, e.g., you have a variable called "square" that holds the result of a square-root operation.
P.S. You need to add some error checking in case the user enters non-numeric data. Check that the result of parseFloat()
is not NaN
. I'd be inclined to do an initial loop through the array parsing and checking for valid numbers, storing the parsed numbers in a second array (or writing them back to the first array), and if any are invalid give the user an error message at that point and stop. Then in your actual calculations you don't have to worry about parsing as you go (or, in your case, parsing again in the second loop).
This function works and produces the same result as numjs
const st = (numbers) => {
const mean = numbers.reduce((acc, item) => acc + item) / numbers.length;
return Math.sqrt(numbers.reduce((acc, item) => acc + Math.pow((parseFloat(item) -mean), 2)))
}
For anyone looking for a more generic solution, here's a standard deviation function added to the Array#. The function expects to be called on an array of numbers.
Array.prototype.stanDeviate = function(){
var i,j,total = 0, mean = 0, diffSqredArr = [];
for(i=0;i<this.length;i+=1){
total+=this[i];
}
mean = total/this.length;
for(j=0;j<this.length;j+=1){
diffSqredArr.push(Math.pow((this[j]-mean),2));
}
return (Math.sqrt(diffSqredArr.reduce(function(firstEl, nextEl){
return firstEl + nextEl;
})/this.length));
};