Calculating Standard Deviation using PowerShell

I have been reading a book on data science recently, and as a result I have had to revisit my high school maths!
One interesting thing I found is that there is more than one way to calculate the end result, and that the standard taught method may not be the most accurate!
The most accurate (according to the experts) is a method created by B.P.Welford, which is detailed in-depth in Donald Knuth’s ‘Art of computer programming’.

My brain thought “I wonder if anyone has implemented this in PowerShell”?

I found it in many difference languages, but not PowerShell, so I thought I would take someone else’s hard work and translate!

The site I choose is https://blog.logentries.com/2016/10/overview-of-online-algorithm-using-standard-deviation-example/#Welford

My version does not yet work as a class where you may ‘pop’ on another value dynamically, it assumes instead that you have the figures, and you would like to work out the Standard Deviation using either a Sample or a Population variance.

The code is as follows:


function Get-StandardDeviation {
    [CmdletBinding()]
    Param (
    # Array of double values
    [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
    [ValidateNotNullOrEmpty()]
    [double[]]$Values
    )
    Begin {
        $count=0.0
        $mean=0.0
        $sum=0.0
    }#begin

    Process {
        foreach ($value in $values) {
            ++$count
            $delta = $mean + (($value - $mean) / $count)
            $sum += ($value - $mean) * ($value - $delta)
            $mean = $delta
        }#foreach
    } # process

    End {
        $VariancePopulation = $sum/($count)
        $VarianceSample = $sum/($count-1)
        $obj=[PSCustomObject]@{
            "VariancePopulation" = $VariancePopulation
            "VarianceSample" = $VarianceSample
            "STDEVPopulation" = [Math]::Sqrt($VariancePopulation)
            "STDEVSample" = [Math]::Sqrt($VarianceSample)
            "Mean" = $mean
            "Count" = $count
        }#obj
        Write-Output $obj
    } #end

}#function

To test this, create an array of doubles, and then use either method shown below to get the results.

$data = (50.0, 45.0, 55.0, 58.0, 43.0, 49.0, 50.0)</code>

Get-StandardDeviation -Values $data
$data | Get-StandardDeviation

Advertisements