├── Tests ├── README.md ├── Show-Measurement.Tests.ps1 ├── Get-InterarrivalTime.Tests.ps1 ├── ConvertFrom-PrimitiveType.Tests.ps1 ├── Measure-Group.Tests.ps1 ├── ConvertFrom-PerformanceCounter.Tests.ps1 ├── Measure-Object.Tests.ps1 ├── Get-SlidingAverage.Tests.ps1 ├── New-RangeString.Tests.ps1 ├── Get-WeightedValue.Tests.ps1 ├── Get-ExampleTimeSeries.Tests.ps1 ├── Get-Histogram.Tests.ps1 ├── Add-Bar.Tests.ps1 └── Expand-DateTime.Tests.ps1 ├── docs ├── en-US │ ├── README.md │ ├── ConvertFrom-PrimitiveType.md │ ├── Measure-Group.md │ ├── ConvertFrom-PerformanceCounter.md │ ├── Expand-DateTime.md │ ├── Get-SlidingAverage.md │ ├── Get-WeightedValue.md │ ├── Get-InterarrivalTime.md │ ├── Show-Measurement.md │ ├── Add-Bar.md │ ├── Get-Histogram.md │ └── Measure-Object.md └── docs.Tests.ps1 ├── .gitignore ├── Examples └── ProcessWorkingSet.ps1 ├── Statistics ├── ConvertFrom-PrimitiveType.ps1 ├── Measure-Group.ps1 ├── Statistics.psm1 ├── ConvertFrom-PerformanceCounter.ps1 ├── Get-ExampleTimeSeries.ps1 ├── Get-WeightedValue.ps1 ├── Get-InterarrivalTime.ps1 ├── HistogramBucket.Format.ps1xml ├── Get-SlidingAverage.ps1 ├── Expand-DateTime.ps1 ├── New-RangeString.ps1 ├── HistogramBar.Format.ps1xml ├── Statistics.psd1 ├── Add-Bar.ps1 ├── Show-Measurement.ps1 ├── Get-Histogram.ps1 └── Measure-Object.ps1 ├── appveyor.yml ├── RELEASENOTES.md ├── README.md └── LICENSE /Tests/README.md: -------------------------------------------------------------------------------- 1 | Place your tests in files called `CMDLET.Tests.ps1` -------------------------------------------------------------------------------- /docs/en-US/README.md: -------------------------------------------------------------------------------- 1 | Place your documentation in files called `CMDLET.md` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Statistics/en-US/*.xml 2 | *.zip 3 | *.clixml 4 | TestResults*.xml 5 | CodeCoverage*.json 6 | dev/* 7 | data/* -------------------------------------------------------------------------------- /Examples/ProcessWorkingSet.ps1: -------------------------------------------------------------------------------- 1 | #region Source functions 2 | Import-Module Statistics 3 | #endregion 4 | 5 | #region Data 6 | $values = Get-Process | select Name,Id,WorkingSet 7 | #endregion 8 | 9 | #region Histogram 10 | $bucket = Get-Histogram -InputObject $values -Property WorkingSet -BucketWidth 5mb -Minimum 0 -Maximum 50mb 11 | $histogram = $bucket | Add-Bar -Property Count 12 | $histogram 13 | #endregion 14 | 15 | #region Measurements 16 | $stats = Measure-Object -InputObject $values -Property WorkingSet 17 | $stats | Show-Measurement 18 | #endregion 19 | -------------------------------------------------------------------------------- /docs/docs.Tests.ps1: -------------------------------------------------------------------------------- 1 | Get-ChildItem -Path $env:BHProjectPath\docs -Directory | Select-Object -ExpandProperty Name | ForEach-Object { 2 | "Compiling help for $_" 3 | 4 | Describe "Documentation for $_" { 5 | Get-Command -Module $env:ModuleName -CommandType Function | Select-Object -ExpandProperty Name | ForEach-Object { 6 | Context "Function $_" { 7 | $help = Get-Help -Name $_ 8 | It 'Defines description' { 9 | $help.description | Should Not Be '' 10 | } 11 | It 'Defines synopsis' { 12 | $help.synopsis | Should Not Be '' 13 | } 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Statistics/ConvertFrom-PrimitiveType.ps1: -------------------------------------------------------------------------------- 1 | function ConvertFrom-PrimitiveType { 2 | [CmdletBinding()] 3 | param( 4 | [Parameter(Mandatory,ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | $InputObject 7 | ) 8 | 9 | Process { 10 | Write-Debug ('[{0}] Entered process block' -f $MyInvocation.MyCommand) 11 | 12 | $InputObject | ForEach-Object { 13 | if (-Not $_.GetType().IsPrimitive) { 14 | throw ('[{0}] Value is not a primitive type' -f $MyInvocation.MyCommand) 15 | } 16 | 17 | [pscustomobject]@{ 18 | Value = $_ 19 | } 20 | } 21 | } 22 | } 23 | 24 | New-Alias -Name cfpt -Value ConvertFrom-PrimitiveType -Force -------------------------------------------------------------------------------- /Statistics/Measure-Group.ps1: -------------------------------------------------------------------------------- 1 | function Measure-Group { 2 | [CmdletBinding()] 3 | param( 4 | [Parameter(Mandatory,ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | [Microsoft.PowerShell.Commands.GroupInfo[]] 7 | $InputObject 8 | , 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property 13 | ) 14 | 15 | Process { 16 | $InputObject | ForEach-Object { 17 | $Measurement = Measure-Object -Data $_.Group -Property $Property 18 | 19 | Add-Member -InputObject $Measurement -MemberType NoteProperty -Name Name -Value $_.Name -PassThru 20 | } 21 | } 22 | } 23 | 24 | New-Alias -Name mg -Value Measure-Group -Force -------------------------------------------------------------------------------- /Statistics/Statistics.psm1: -------------------------------------------------------------------------------- 1 | #region Helpers 2 | . "$PSScriptRoot\Get-ExampleTimeSeries.ps1" 3 | . "$PSScriptRoot\New-RangeString.ps1" 4 | #endregion 5 | 6 | #region Overloading 7 | . "$PSScriptRoot\Measure-Object.ps1" 8 | #endregion 9 | 10 | #region Conversions 11 | . "$PSScriptRoot\ConvertFrom-PrimitiveType.ps1" 12 | . "$PSScriptRoot\ConvertFrom-PerformanceCounter.ps1" 13 | . "$PSScriptRoot\Expand-DateTime.ps1" 14 | #endregion 15 | 16 | #region Analysis 17 | . "$PSScriptRoot\Get-Histogram.ps1" 18 | . "$PSScriptRoot\Measure-Group.ps1" 19 | . "$PSScriptRoot\Get-InterarrivalTime.ps1" 20 | . "$PSScriptRoot\Get-SlidingAverage.ps1" 21 | . "$PSScriptRoot\Get-WeightedValue.ps1" 22 | #endregion 23 | 24 | #region Visualization 25 | . "$PSScriptRoot\Add-Bar.ps1" 26 | . "$PSScriptRoot\Show-Measurement.ps1" 27 | #endregion -------------------------------------------------------------------------------- /Statistics/ConvertFrom-PerformanceCounter.ps1: -------------------------------------------------------------------------------- 1 | function ConvertFrom-PerformanceCounter { 2 | [CmdletBinding()] 3 | param( 4 | [Parameter(Mandatory,ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $InputObject 8 | , 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Instance 13 | ) 14 | 15 | Process { 16 | $InputObject | ForEach-Object { 17 | [pscustomobject]@{ 18 | Timestamp = $_.Timestamp 19 | Value = $_.CounterSamples | Where-Object { $_.InstanceName -ieq $Instance } | Select-Object -ExpandProperty CookedValue 20 | } 21 | } 22 | } 23 | } 24 | 25 | New-Alias -Name cfpc -Value ConvertFrom-PerformanceCounter -Force -------------------------------------------------------------------------------- /Tests/Show-Measurement.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Show-Measurement' { 12 | $data = 0..10 | ConvertFrom-PrimitiveType 13 | $stats = Measure-Object -Data $data -Property Value 14 | It 'Produces output' { 15 | Mock Write-Host {} 16 | Show-Measurement -InputObject $stats 17 | Assert-MockCalled Write-Host -Scope It -Times 1 -Exactly 18 | } 19 | It 'Produces input object' { 20 | Mock Write-Host {} 21 | $input = Show-Measurement -InputObject $stats -PassThru 22 | $input | Should Be $stats 23 | } 24 | } -------------------------------------------------------------------------------- /Tests/Get-InterarrivalTime.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Get-InterarrivalTime' { 12 | $now = Get-Date 13 | $data = 1..10 | ForEach-Object { 14 | [pscustomobject]@{ 15 | Timestamp = Get-Random -Minimum $now.AddDays(-1).Ticks -Maximum $now.Ticks 16 | Value = Get-Random -Minimum 0 -Maximum 100 17 | } 18 | } | Sort-Object -Property Timestamp 19 | It 'Produces the correct members' { 20 | $data = $data | Get-InterarrivalTime -Property Timestamp 21 | { $data | Select-Object -ExpandProperty InterarrivalTicks -ErrorAction SilentlyContinue } | Should Not Throw 22 | } 23 | } -------------------------------------------------------------------------------- /Tests/ConvertFrom-PrimitiveType.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'ConvertFrom-PrimitiveType' { 12 | $array = @(1, 2, 3) 13 | It 'Produces output from parameter' { 14 | $data = ConvertFrom-PrimitiveType -InputObject $array 15 | $data -is [array] | Should Be $true 16 | $data.Length | Should Be $array.Length 17 | } 18 | It 'Produces output from pipeline' { 19 | $data = $array | ConvertFrom-PrimitiveType 20 | $data -is [array] | Should Be $true 21 | $data.Length | Should Be $array.Length 22 | } 23 | It 'Throws on piped complex type' { 24 | { Get-Process | Select-Object -First 1 | ConvertFrom-PrimitiveType } | Should Throw 25 | } 26 | } -------------------------------------------------------------------------------- /Tests/Measure-Group.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Measure-Group' { 12 | It 'Produces correct members' { 13 | $now = Get-Date 14 | $data = 1..10 | ForEach-Object { 15 | [pscustomobject]@{ 16 | Timestamp = Get-Random -Minimum $now.AddDays(-1).Ticks -Maximum $now.Ticks 17 | Value = Get-Random -Minimum 0 -Maximum 100 18 | } 19 | } | Sort-Object -Property Timestamp 20 | $data = $data | Expand-DateTime | Group-Object -Property Hour 21 | $group = Measure-Group -InputObject $data -Property Value 22 | { $group | Select-Object -ExpandProperty Average -ErrorAction SilentlyContinue } | Should Not Throw 23 | } 24 | } -------------------------------------------------------------------------------- /docs/en-US/ConvertFrom-PrimitiveType.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # ConvertFrom-PrimitiveType 8 | 9 | ## SYNOPSIS 10 | Wraps values in objects 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | ConvertFrom-PrimitiveType [-InputObject] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | The cmdlet accepts values in primitive types and wraps them in a new object 20 | 21 | ## EXAMPLES 22 | 23 | ### Example 1 24 | ``` 25 | 1..10 | ConvertFrom-PrimitiveType 26 | 27 | Value 28 | ----- 29 | 1 30 | 2 31 | 3 32 | 4 33 | 5 34 | 6 35 | 7 36 | 8 37 | 9 38 | 10 39 | ``` 40 | 41 | ## PARAMETERS 42 | 43 | ### -InputObject 44 | Input objects containing the relevant data 45 | 46 | ```yaml 47 | Type: Object 48 | Parameter Sets: (All) 49 | Aliases: 50 | 51 | Required: True 52 | Position: 1 53 | Default value: None 54 | Accept pipeline input: True (ByValue) 55 | Accept wildcard characters: False 56 | ``` 57 | 58 | ## INPUTS 59 | 60 | ## OUTPUTS 61 | 62 | ## NOTES 63 | 64 | ## RELATED LINKS 65 | 66 | -------------------------------------------------------------------------------- /Statistics/Get-ExampleTimeSeries.ps1: -------------------------------------------------------------------------------- 1 | function Get-ExampleTimeSeries { 2 | [CmdletBinding()] 3 | param( 4 | [Parameter()] 5 | [ValidateNotNullOrEmpty()] 6 | [int] 7 | $Count = 100 8 | , 9 | [Parameter()] 10 | [ValidateNotNullOrEmpty()] 11 | [datetime] 12 | $Start 13 | , 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [datetime] 17 | $End = (Get-Date) 18 | , 19 | [Parameter()] 20 | [ValidateNotNullOrEmpty()] 21 | [int] 22 | $IntervalDays = 7 23 | ) 24 | 25 | if (-Not $Start) { 26 | $Start = $End.AddDays(-1 * $IntervalDays) 27 | } 28 | 29 | $StartTicks = $Start.Ticks 30 | $EndTicks = $End.Ticks 31 | 32 | 1..$Count | ForEach-Object { 33 | Get-Random -Minimum $StartTicks -Maximum $EndTicks 34 | } | Sort-Object | ForEach-Object { 35 | [pscustomobject]@{ 36 | Timestamp = Get-Date -Date $_ 37 | Value = Get-Random -Minimum 0 -Maximum 100 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Tests/ConvertFrom-PerformanceCounter.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'ConvertFrom-PerformanceCounter' { 12 | It 'Produces the correct properties' { 13 | switch ([CultureInfo]::InstalledUICulture) { 14 | 'de-DE' { 15 | $Counter = '\Prozessor(_Total)\Prozessorzeit (%)' 16 | } 17 | 'en-US' { 18 | $Counter = '\Processor(_Total)\% Processor Time' 19 | } 20 | } 21 | $data = Get-Counter -Counter $Counter | ConvertFrom-PerformanceCounter -Instance _total 22 | { $data | Select-Object -ExpandProperty Timestamp -ErrorAction SilentlyContinue } | Should Not Throw 23 | { $data | Select-Object -ExpandProperty Value -ErrorAction SilentlyContinue } | Should Not Throw 24 | } 25 | } -------------------------------------------------------------------------------- /Tests/Measure-Object.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Measure-Object' { 12 | It 'Produces output from parameter' { 13 | $data = 0..10 | ConvertFrom-PrimitiveType 14 | $Stats = Measure-Object -Data $data -Property Value 15 | $Stats | Select-Object -ExpandProperty Property | Should Be 'Value' 16 | } 17 | It 'Produces correct Median for an odd number of values' { 18 | $data = 0..10 | ConvertFrom-PrimitiveType 19 | $Stats = Measure-Object -Data $data -Property Value 20 | $Stats.Median | Should Be 5 21 | } 22 | It 'Produces correct Median for an even number of values' { 23 | $data = 1..10 | ConvertFrom-PrimitiveType 24 | $Stats = Measure-Object -Data $data -Property Value 25 | $Stats.Median | Should Be 5.5 26 | } 27 | } -------------------------------------------------------------------------------- /Tests/Get-SlidingAverage.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Get-SlidingAverage' { 12 | switch ([CultureInfo]::InstalledUICulture) { 13 | 'de-DE' { 14 | $Counter = '\Prozessor(_Total)\Prozessorzeit (%)' 15 | } 16 | 'en-US' { 17 | $Counter = '\Processor(_Total)\% Processor Time' 18 | } 19 | } 20 | It 'Produces output' { 21 | $data = @(Get-Counter -Counter $Counter -SampleInterval 1 -MaxSamples 6 | ConvertFrom-PerformanceCounter -Instance _total | Get-SlidingAverage -Property Value -Size 5) 22 | $data -is [array] | Should Be $true 23 | $data.Length | Should Be 2 24 | } 25 | It 'Throws on missing property' { 26 | { Get-Counter -Counter $Counter -SampleInterval 1 -MaxSamples 6 | ConvertFrom-PerformanceCounter -Instance _total | Get-SlidingAverage -Property Value2 -Size 5 } | Should Throw 27 | } 28 | } -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | skip_tags: true 3 | 4 | environment: 5 | BuildToolsVersion: '1.1.*' 6 | StatementCoverageThreshold: 100 7 | FunctionCoverageThreshold: 100 8 | #SkipUnitTests: true 9 | #SkipDocumentation: true 10 | #SkipScriptAnalysis: true 11 | NuGetApiKey: 12 | secure: EaMePsm8eU/bUd1Ej83dTOAaGja/ht/3IrKC84nbZ9+dQbjeDfbTHk7nM+wp9DgE 13 | GitHubToken: 14 | secure: LznJHcvQE4ZRnDPWnayvawgr7VSpwH6ImeN6OK6tmLh5UHKdfZu6qKQ+ZBbkei73 15 | 16 | os: WMF 5 17 | 18 | build: false 19 | 20 | test_script: 21 | - ps: >- 22 | $ErrorActionPreference = 'Stop'; 23 | $Response = Invoke-RestMethod -Uri 'https://api.github.com/repos/nicholasdille/powershell-build/releases'; 24 | $Release = $Response | Where-Object { $_.tag_name -like $env:BuildToolsVersion } | Sort-Object -Property tag_name -Descending | Select-Object -First 1; 25 | Write-Host -ForegroundColor Yellow -Message "Using version $($Release.tag_name) of build tools"; 26 | Invoke-WebRequest -Uri $Release.zipball_url -OutFile Build.zip; 27 | Expand-Archive -Path '.\Build.zip' -DestinationPath .; 28 | Remove-Item -Path '.\Build.zip'; 29 | Get-Item -Path nicholasdille-PowerShell-Build-* | Rename-Item -NewName 'Build'; 30 | .\Build\Start-Build.ps1 -Task Deploy -------------------------------------------------------------------------------- /Statistics/Get-WeightedValue.ps1: -------------------------------------------------------------------------------- 1 | function Get-WeightedValue { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory,ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $InputObject 8 | , 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property 13 | , 14 | [Parameter(Mandatory)] 15 | [ValidateNotNullOrEmpty()] 16 | [string] 17 | $WeightProperty 18 | ) 19 | 20 | Process { 21 | $InputObject | ForEach-Object { 22 | if (-Not (Get-Member -InputObject $_ -MemberType Properties -Name $Property)) { 23 | throw ('[{0}] Unable to find property <{1}> in input object' -f $MyInvocation.MyCommand, $Property) 24 | } 25 | if (-Not (Get-Member -InputObject $_ -MemberType Properties -Name $WeightProperty)) { 26 | throw ('[{0}] Unable to find weight property <{1}> in input object' -f $MyInvocation.MyCommand, $WeightProperty) 27 | } 28 | 29 | [pscustomobject]@{ 30 | Value = $_.$WeightProperty * $_.$Property 31 | } 32 | } 33 | } 34 | } 35 | 36 | New-Alias -Name gwv -Value Get-WeightedValue -Force -------------------------------------------------------------------------------- /Tests/New-RangeString.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'New-RangeString' { 12 | It 'Works with both indexes in bounds' { 13 | New-RangeString -Width 10 -LeftIndex 2 -RightIndex 8 | Should Be ' |-----|' 14 | } 15 | It 'Works with left index out of bounds' { 16 | New-RangeString -Width 10 -LeftIndex -2 -RightIndex 8 | Should Be '<------|' 17 | } 18 | It 'Works with both right index out of bounds' { 19 | New-RangeString -Width 10 -LeftIndex 2 -RightIndex 12 | Should Be ' |------->' 20 | } 21 | It 'Works with both indexes out of bounds' { 22 | New-RangeString -Width 10 -LeftIndex -2 -RightIndex 12 | Should Be '<-------->' 23 | } 24 | It 'Works with identical indexes' { 25 | New-RangeString -Width 10 -LeftIndex 2 -RightIndex 2 | Should Be ' ||' 26 | } 27 | It 'Works with zero indexes' { 28 | New-RangeString -Width 10 -LeftIndex 0 -RightIndex 0 | Should Be '||' 29 | } 30 | } -------------------------------------------------------------------------------- /docs/en-US/Measure-Group.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # Measure-Group 8 | 9 | ## SYNOPSIS 10 | {{Fill in the Synopsis}} 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Measure-Group [-InputObject] [-Property] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | {{Fill in the Description}} 20 | 21 | ## EXAMPLES 22 | 23 | ### Example 1 24 | ``` 25 | PS C:\> {{ Add example code here }} 26 | ``` 27 | 28 | {{ Add example description here }} 29 | 30 | ## PARAMETERS 31 | 32 | ### -InputObject 33 | {{Fill InputObject Description}} 34 | 35 | ```yaml 36 | Type: GroupInfo[] 37 | Parameter Sets: (All) 38 | Aliases: 39 | 40 | Required: True 41 | Position: 0 42 | Default value: None 43 | Accept pipeline input: True (ByValue) 44 | Accept wildcard characters: False 45 | ``` 46 | 47 | ### -Property 48 | {{Fill Property Description}} 49 | 50 | ```yaml 51 | Type: String 52 | Parameter Sets: (All) 53 | Aliases: 54 | 55 | Required: True 56 | Position: 1 57 | Default value: None 58 | Accept pipeline input: False 59 | Accept wildcard characters: False 60 | ``` 61 | 62 | ## INPUTS 63 | 64 | ### Microsoft.PowerShell.Commands.GroupInfo[] 65 | 66 | ## OUTPUTS 67 | 68 | ### System.Object 69 | 70 | ## NOTES 71 | 72 | ## RELATED LINKS 73 | 74 | -------------------------------------------------------------------------------- /Tests/Get-WeightedValue.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Get-WeightedValue' { 12 | It 'Throws on missing property' { 13 | $data = [pscustomobject]@{ 14 | Vaule = 5 15 | Weight = 2 16 | } 17 | { $data | Get-WeightedValue -Property Value -WeightProperty Weight } | Should Throw 18 | } 19 | It 'Throws on missing weight property' { 20 | $data = [pscustomobject]@{ 21 | Value = 5 22 | Weigth = 2 23 | } 24 | { $data | Get-WeightedValue -Property Value -WeightProperty Weight } | Should Throw 25 | } 26 | It 'Produces the correct members' { 27 | $data = [pscustomobject]@{ 28 | Value = 5 29 | Weight = 2 30 | } 31 | $result = @($data | Get-WeightedValue -Property Value -WeightProperty Weight) 32 | $result -is [array] | Should Be $true 33 | $result.Length | Should Be 1 34 | { $result[0] | Select-Object -ExpandProperty Value -ErrorAction SilentlyContinue } | Should Not Throw 35 | } 36 | } -------------------------------------------------------------------------------- /docs/en-US/ConvertFrom-PerformanceCounter.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # ConvertFrom-PerformanceCounter 8 | 9 | ## SYNOPSIS 10 | {{Fill in the Synopsis}} 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | ConvertFrom-PerformanceCounter [-InputObject] [-Instance] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | {{Fill in the Description}} 20 | 21 | ## EXAMPLES 22 | 23 | ### Example 1 24 | ``` 25 | Get-counter -Counter "\Processor(_Total)\% Processor Time" -SampleInterval 2 -MaxSamples 100 | ConvertFrom-PerformanceCounter 26 | ``` 27 | 28 | {{ Add example description here }} 29 | 30 | ## PARAMETERS 31 | 32 | ### -InputObject 33 | {{Fill InputObject Description}} 34 | 35 | ```yaml 36 | Type: Array 37 | Parameter Sets: (All) 38 | Aliases: 39 | 40 | Required: True 41 | Position: 0 42 | Default value: None 43 | Accept pipeline input: True (ByValue) 44 | Accept wildcard characters: False 45 | ``` 46 | 47 | ### -Instance 48 | {{Fill Instance Description}} 49 | 50 | ```yaml 51 | Type: String 52 | Parameter Sets: (All) 53 | Aliases: 54 | 55 | Required: True 56 | Position: 1 57 | Default value: None 58 | Accept pipeline input: False 59 | Accept wildcard characters: False 60 | ``` 61 | 62 | ## INPUTS 63 | 64 | ### System.Array 65 | 66 | ## OUTPUTS 67 | 68 | ### System.Object 69 | 70 | ## NOTES 71 | 72 | ## RELATED LINKS 73 | 74 | -------------------------------------------------------------------------------- /Statistics/Get-InterarrivalTime.ps1: -------------------------------------------------------------------------------- 1 | function Get-InterarrivalTime { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory,ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $InputObject 8 | , 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property 13 | , 14 | [Parameter()] 15 | [ValidateSet('Ticks', 'TotalSecond', 'Minutes', 'Hours', 'Days')] 16 | [string] 17 | $Unit = 'Ticks' 18 | ) 19 | 20 | Begin { 21 | Write-Debug ('[{0}] Entering begin block' -f $MyInvocation.MyCommand) 22 | $PreviousArrival = $null 23 | } 24 | 25 | Process { 26 | Write-Debug ('[{0}] Entering process block' -f $MyInvocation.MyCommand) 27 | $InputObject | ForEach-Object { 28 | Write-Debug ('[{0}] Processing value' -f $MyInvocation.MyCommand) 29 | if ($PreviousArrival) { 30 | Write-Debug ('[{0}] Calculating interarrival time' -f $MyInvocation.MyCommand) 31 | Add-Member -InputObject $_ -MemberType NoteProperty -Name "Interarrival$Unit" -Value (New-TimeSpan -Start $PreviousArrival.$Property -End $_.$Property | Select-Object -ExpandProperty $Unit) -PassThru 32 | } 33 | $PreviousArrival = $_ 34 | } 35 | } 36 | } 37 | 38 | New-Alias -Name giat -Value Get-InterarrivalTime -Force -------------------------------------------------------------------------------- /RELEASENOTES.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | 3 | ## 1.2.0.149 4 | 5 | - Switched to four part version numbers 6 | - Migrated to centralized build tools 7 | - Migrated to new format of release notes 8 | 9 | ## 1.1.148 10 | 11 | - Fixed upload to Coveralls 12 | - Improved quality by honouring findings of script analyzer 13 | 14 | ## 1.1.136 15 | 16 | - Added behaviour to skip build steps 17 | - Relying on the module CICD 18 | - Fixed behaviour in CICD module 19 | 20 | ## 1.1.123 21 | 22 | - Integrated updated scripts from PowerShell-CI 23 | - Fixed test for property 24 | - Added link to PSGallery in GitHub release 25 | - Fixed markdown spacing in release notes 26 | - Fixed naming of release asset 27 | - Enhanced code coverage metrics 28 | - Fixed project directory 29 | - Fixed performance monitor counter names 30 | - Fixed behaviour without network connectivity 31 | - Testing documentation 32 | - Fixed output directory of documentation 33 | 34 | ## 1.1.64 35 | 36 | - Improved check for data via parameter or pipeline 37 | - Added automatic creation of GitHub release 38 | - Fixed variable name due to upstream change (BHPSModulePath --> BHModulePath) 39 | - Fixed type casting (GitHub issue #1) 40 | 41 | ## 1.1.53 42 | 43 | Performance improvements 44 | 45 | ## 1.1.46 46 | 47 | Fix for calculation of variance 48 | 49 | ## 1.1.43 50 | 51 | Added cmdlets for analyzing time series and stream processing data 52 | 53 | ## 1.0.34 54 | 55 | Fixes problem with classes in modules by removing them 56 | 57 | ## 1.0.29 58 | 59 | Initial release 60 | -------------------------------------------------------------------------------- /Statistics/HistogramBucket.Format.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | HistogramView 7 | 8 | HistogramBucket 9 | 10 | 11 | 12 | 13 | 14 | 5 15 | Right 16 | 17 | 18 | 10 19 | Right 20 | 21 | 22 | 23 | 24 | 25 | 26 | Index 27 | 28 | 29 | Count 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/en-US/Expand-DateTime.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # Expand-DateTime 8 | 9 | ## SYNOPSIS 10 | {{Fill in the Synopsis}} 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Expand-DateTime [-InputObject] [[-Property] ] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | {{Fill in the Description}} 20 | 21 | ## EXAMPLES 22 | 23 | ### Example 1 24 | ``` 25 | 1..10 | ForEach-Object { 26 | Get-Counter -Counter '\Processor(_Total)\% Processor Time' 27 | } | ConvertFrom-PerformanceCounter | ForEach-Object { 28 | [pscustomobject]@{ 29 | Timestamp = $_.Timestamp.DateTime 30 | Value = $_.Value 31 | } 32 | } | Expand-DateTime -Property Timestamp 33 | ``` 34 | 35 | {{ Add example description here }} 36 | 37 | ## PARAMETERS 38 | 39 | ### -InputObject 40 | {{Fill InputObject Description}} 41 | 42 | ```yaml 43 | Type: Array 44 | Parameter Sets: (All) 45 | Aliases: 46 | 47 | Required: True 48 | Position: 0 49 | Default value: None 50 | Accept pipeline input: True (ByValue) 51 | Accept wildcard characters: False 52 | ``` 53 | 54 | ### -Property 55 | {{Fill Property Description}} 56 | 57 | ```yaml 58 | Type: String 59 | Parameter Sets: (All) 60 | Aliases: 61 | 62 | Required: False 63 | Position: 1 64 | Default value: None 65 | Accept pipeline input: False 66 | Accept wildcard characters: False 67 | ``` 68 | 69 | ## INPUTS 70 | 71 | ### System.Array 72 | 73 | ## OUTPUTS 74 | 75 | ### System.Object 76 | 77 | ## NOTES 78 | 79 | ## RELATED LINKS 80 | 81 | -------------------------------------------------------------------------------- /docs/en-US/Get-SlidingAverage.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # Get-SlidingAverage 8 | 9 | ## SYNOPSIS 10 | {{Fill in the Synopsis}} 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Get-SlidingAverage [-InputObject] [-Property] [[-Size] ] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | {{Fill in the Description}} 20 | 21 | ## EXAMPLES 22 | 23 | ### Example 1 24 | ``` 25 | PS C:\> {{ Add example code here }} 26 | ``` 27 | 28 | {{ Add example description here }} 29 | 30 | ## PARAMETERS 31 | 32 | ### -InputObject 33 | {{Fill InputObject Description}} 34 | 35 | ```yaml 36 | Type: Array 37 | Parameter Sets: (All) 38 | Aliases: 39 | 40 | Required: True 41 | Position: 0 42 | Default value: None 43 | Accept pipeline input: True (ByValue) 44 | Accept wildcard characters: False 45 | ``` 46 | 47 | ### -Property 48 | {{Fill Property Description}} 49 | 50 | ```yaml 51 | Type: String 52 | Parameter Sets: (All) 53 | Aliases: 54 | 55 | Required: True 56 | Position: 1 57 | Default value: None 58 | Accept pipeline input: False 59 | Accept wildcard characters: False 60 | ``` 61 | 62 | ### -Size 63 | {{Fill Size Description}} 64 | 65 | ```yaml 66 | Type: Int32 67 | Parameter Sets: (All) 68 | Aliases: 69 | 70 | Required: False 71 | Position: 2 72 | Default value: None 73 | Accept pipeline input: False 74 | Accept wildcard characters: False 75 | ``` 76 | 77 | ## INPUTS 78 | 79 | ### System.Array 80 | 81 | ## OUTPUTS 82 | 83 | ### System.Object 84 | 85 | ## NOTES 86 | 87 | ## RELATED LINKS 88 | 89 | -------------------------------------------------------------------------------- /docs/en-US/Get-WeightedValue.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # Get-WeightedValue 8 | 9 | ## SYNOPSIS 10 | {{Fill in the Synopsis}} 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Get-WeightedValue [-InputObject] [-Property] [-WeightProperty] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | {{Fill in the Description}} 20 | 21 | ## EXAMPLES 22 | 23 | ### Example 1 24 | ``` 25 | PS C:\> {{ Add example code here }} 26 | ``` 27 | 28 | {{ Add example description here }} 29 | 30 | ## PARAMETERS 31 | 32 | ### -InputObject 33 | {{Fill InputObject Description}} 34 | 35 | ```yaml 36 | Type: Array 37 | Parameter Sets: (All) 38 | Aliases: 39 | 40 | Required: True 41 | Position: 0 42 | Default value: None 43 | Accept pipeline input: True (ByValue) 44 | Accept wildcard characters: False 45 | ``` 46 | 47 | ### -Property 48 | {{Fill Property Description}} 49 | 50 | ```yaml 51 | Type: String 52 | Parameter Sets: (All) 53 | Aliases: 54 | 55 | Required: True 56 | Position: 1 57 | Default value: None 58 | Accept pipeline input: False 59 | Accept wildcard characters: False 60 | ``` 61 | 62 | ### -WeightProperty 63 | {{Fill WeightProperty Description}} 64 | 65 | ```yaml 66 | Type: String 67 | Parameter Sets: (All) 68 | Aliases: 69 | 70 | Required: True 71 | Position: 2 72 | Default value: None 73 | Accept pipeline input: False 74 | Accept wildcard characters: False 75 | ``` 76 | 77 | ## INPUTS 78 | 79 | ### System.Array 80 | 81 | ## OUTPUTS 82 | 83 | ### System.Object 84 | 85 | ## NOTES 86 | 87 | ## RELATED LINKS 88 | 89 | -------------------------------------------------------------------------------- /Tests/Get-ExampleTimeSeries.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Get-ExampleTimeSeries' { 12 | $end = (Get-Date) 13 | $start = $end.AddDays(-3) 14 | $count = 25 15 | $data = Get-ExampleTimeSeries -Start $start -End $end -Count $count 16 | It 'Produces data of correct length' { 17 | $data -is [array] | Should Be $true 18 | $data.Length | Should Be $count 19 | } 20 | It 'Honours the defined time range' { 21 | $stats = $data | Microsoft.PowerShell.Utility\Measure-Object -Property Timestamp -Minimum -Maximum 22 | $stats.Minimum | Should BeGreaterThan $start 23 | $stats.Maximum | Should BeLessThan $end 24 | } 25 | It 'Produces the correct range of values' { 26 | $stats = $data | Microsoft.PowerShell.Utility\Measure-Object -Property Value -Minimum -Maximum 27 | $stats.Minimum -ge 0 | Should Be $true 28 | $stats.Maximum | Should BeLessThan 100 29 | } 30 | It 'Calculated the time range correctly' { 31 | $data = Get-ExampleTimeSeries -Interval 3 -Count $count 32 | $stats = $data | Microsoft.PowerShell.Utility\Measure-Object -Property Timestamp -Minimum -Maximum 33 | $stats.Minimum | Should BeGreaterThan $start 34 | $stats.Maximum | Should BeLessThan $end 35 | } 36 | } -------------------------------------------------------------------------------- /Tests/Get-Histogram.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Get-Histogram' { 12 | $data = 1..10 | ConvertFrom-PrimitiveType 13 | It 'Produces output from parameter' { 14 | $histogram = Get-Histogram -Data $data -Property Value 15 | $histogram -is [array] | Should Be $true 16 | $histogram.Length | Should Be 9 17 | } 18 | It 'Produces output type [HistogramBucket]' { 19 | $item = Get-Histogram -Data $data -Property Value | Select-Object -First 1 20 | $item.PSTypeNames -contains 'HistogramBucket' | Should Be $true 21 | } 22 | It 'Honors minimum and maximum values' { 23 | $histogram = Get-Histogram -Data $data -Property Value -Minimum 2 -Maximum 5 24 | $histogram | Select-Object -First 1 -ExpandProperty lowerBound | Should Be 2 25 | $histogram | Select-Object -Last 1 -ExpandProperty upperBound | Should Be 5 26 | } 27 | It 'Warns for large number of buckets' { 28 | $data = 1..110 | ConvertFrom-PrimitiveType 29 | Mock Write-Warning {} 30 | Get-Histogram -Data $data -Property Value 31 | Assert-MockCalled -CommandName Write-Warning -Times 1 -Exactly 32 | } 33 | It 'Produces empty histogram' { 34 | $data = 1..10 + 20..30 | ConvertFrom-PrimitiveType 35 | $histogram = Get-Histogram -Data $data -Property Value -Minimum 11 -Maximum 19 36 | $histogram 37 | } 38 | } -------------------------------------------------------------------------------- /Statistics/Get-SlidingAverage.ps1: -------------------------------------------------------------------------------- 1 | function Get-SlidingAverage { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory,ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $InputObject 8 | , 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property 13 | , 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [int] 17 | $Size = 5 18 | ) 19 | 20 | Begin { 21 | Write-Debug ('[{0}] Size of queue is <{1}>' -f $MyInvocation.MyCommand, $q.Count) 22 | $q = New-Object -TypeName System.Collections.Queue -ArgumentList $Size 23 | } 24 | 25 | Process { 26 | $InputObject | ForEach-Object { 27 | if (-Not (Get-Member -InputObject $_ -MemberType Properties -Name $Property)) { 28 | throw ('[{0}] Unable to find property <{1}> in input object' -f $MyInvocation.MyCommand, $Property) 29 | } 30 | 31 | #region Enqueue new item and trim to specified size 32 | $q.Enqueue($_) 33 | Write-Debug ('[{0}] Size of queue is <{1}>' -f $MyInvocation.MyCommand, $q.Count) 34 | if ($q.Count -gt $Size) { 35 | $q.Dequeue() | Out-Null 36 | } 37 | #endregion 38 | 39 | #region Calculate average if the specified number of items is present 40 | if ($q.Count -eq $Size) { 41 | $q | Microsoft.PowerShell.Utility\Measure-Object -Property $Property -Average | Select-Object -ExpandProperty Average 42 | } 43 | #endregion 44 | } 45 | } 46 | } 47 | 48 | New-Alias -Name gsa -Value Get-SlidingAverage -Force -------------------------------------------------------------------------------- /Statistics/Expand-DateTime.ps1: -------------------------------------------------------------------------------- 1 | function Expand-DateTime { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory,ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $InputObject 8 | , 9 | [Parameter()] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property = 'Timestamp' 13 | ) 14 | 15 | Process { 16 | Write-Debug ('[{0}] Entering process block' -f $MyInvocation.MyCommand) 17 | $InputObject | ForEach-Object { 18 | Write-Debug 'inside foreach' 19 | if (-Not (Get-Member -InputObject $_ -MemberType Properties -Name $Property)) { 20 | throw ('[{0}] Unable to find property <{1}> in input object' -f $MyInvocation.MyCommand, $Property) 21 | } 22 | 23 | $DateTimeExpanded = $_.$Property 24 | if ($DateTimeExpanded -isnot [System.DateTime]) { 25 | Write-Debug 'inside if' 26 | $DateTimeExpanded = Get-Date -Date $_.$Property 27 | $_.$Property = $DateTimeExpanded 28 | } 29 | 30 | foreach ($DateTimeProperty in @('DayOfWeek')) { 31 | Add-Member -InputObject $_ -MemberType NoteProperty -Name $DateTimeProperty -Value $DateTimeExpanded.$DateTimeProperty 32 | } 33 | foreach ($DateTimeProperty in @('Year', 'Month', 'Hour')) { 34 | Add-Member -InputObject $_ -MemberType NoteProperty -Name $DateTimeProperty -Value ([int]($DateTimeExpanded.$DateTimeProperty)) 35 | } 36 | Add-Member -InputObject $_ -MemberType NoteProperty -Name WeekOfYear -Value ([int](Get-Date -Date $_.$Property -UFormat '%V')) 37 | 38 | $_ 39 | } 40 | } 41 | } 42 | 43 | New-Alias -Name edt -Value Expand-DateTime -Force -------------------------------------------------------------------------------- /docs/en-US/Get-InterarrivalTime.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # Get-InterarrivalTime 8 | 9 | ## SYNOPSIS 10 | {{Fill in the Synopsis}} 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Get-InterarrivalTime [-InputObject] [-Property] [[-Unit] ] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | {{Fill in the Description}} 20 | 21 | ## EXAMPLES 22 | 23 | ### Example 1 24 | ``` 25 | 1..10 | ForEach-Object { 26 | Get-Counter -Counter '\Processor(_Total)\% Processor Time' 27 | Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 5) 28 | } | ConvertFrom-PerformanceCounter | Get-InterarrivalTime -Property Timestamp 29 | ``` 30 | 31 | {{ Add example description here }} 32 | 33 | ## PARAMETERS 34 | 35 | ### -InputObject 36 | {{Fill InputObject Description}} 37 | 38 | ```yaml 39 | Type: Array 40 | Parameter Sets: (All) 41 | Aliases: 42 | 43 | Required: True 44 | Position: 0 45 | Default value: None 46 | Accept pipeline input: True (ByValue) 47 | Accept wildcard characters: False 48 | ``` 49 | 50 | ### -Property 51 | {{Fill Property Description}} 52 | 53 | ```yaml 54 | Type: String 55 | Parameter Sets: (All) 56 | Aliases: 57 | 58 | Required: True 59 | Position: 1 60 | Default value: None 61 | Accept pipeline input: False 62 | Accept wildcard characters: False 63 | ``` 64 | 65 | ### -Unit 66 | {{Fill Unit Description}} 67 | 68 | ```yaml 69 | Type: String 70 | Parameter Sets: (All) 71 | Aliases: 72 | Accepted values: Ticks, TotalSecond, Minutes, Hours, Days 73 | 74 | Required: False 75 | Position: 2 76 | Default value: None 77 | Accept pipeline input: False 78 | Accept wildcard characters: False 79 | ``` 80 | 81 | ## INPUTS 82 | 83 | ### System.Array 84 | 85 | ## OUTPUTS 86 | 87 | ### System.Object 88 | 89 | ## NOTES 90 | 91 | ## RELATED LINKS 92 | 93 | -------------------------------------------------------------------------------- /Statistics/New-RangeString.ps1: -------------------------------------------------------------------------------- 1 | function New-RangeString { 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 3 | "PSUseShouldProcessForStateChangingFunctions", 4 | "", 5 | Justification = "Creates in-memory object only." 6 | )] 7 | [CmdletBinding()] 8 | param( 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [int] 12 | $Width 13 | , 14 | [Parameter(Mandatory)] 15 | [ValidateNotNullOrEmpty()] 16 | [int] 17 | $LeftIndex 18 | , 19 | [Parameter(Mandatory)] 20 | [ValidateNotNullOrEmpty()] 21 | [int] 22 | $RightIndex 23 | , 24 | [Parameter()] 25 | [ValidateNotNullOrEmpty()] 26 | [string] 27 | $LeftIndicator = '|' 28 | , 29 | [Parameter()] 30 | [ValidateNotNullOrEmpty()] 31 | [string] 32 | $RightIndicator = '|' 33 | ) 34 | 35 | Write-Debug ('[{0}] Width={1} LeftIndex={2} RightIndex={3}' -f $MyInvocation.MyCommand, $Width, $LeftIndex, $RightIndex) 36 | if ($LeftIndex -lt 0) { 37 | $LeftIndex = 1 38 | $LeftIndicator = '<' 39 | } 40 | if ($LeftIndex -eq 0) { 41 | $LeftIndex = 1 42 | } 43 | Write-Debug ('[{0}] Width={1} LeftIndex={2} RightIndex={3}' -f $MyInvocation.MyCommand, $Width, $LeftIndex, $RightIndex) 44 | $line = ' ' * ($LeftIndex - 1) + $LeftIndicator 45 | if ($RightIndex -gt $Width) { 46 | $RightIndex = $Width 47 | $RightIndicator = '>' 48 | } 49 | Write-Debug ('[{0}] Width={1} LeftIndex={2} RightIndex={3}' -f $MyInvocation.MyCommand, $Width, $LeftIndex, $RightIndex) 50 | if ($RightIndex -gt $LeftIndex) { 51 | $line += '-' * ($RightIndex - $LeftIndex - 1) 52 | } 53 | $line += $RightIndicator 54 | 55 | $line 56 | } -------------------------------------------------------------------------------- /Statistics/HistogramBar.Format.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | HistogramView 7 | 8 | HistogramBar 9 | 10 | 11 | 12 | 13 | 14 | 5 15 | Right 16 | 17 | 18 | 10 19 | Right 20 | 21 | 22 | 30 23 | Left 24 | 25 | 26 | 27 | 28 | 29 | 30 | Index 31 | 32 | 33 | Count 34 | 35 | 36 | Bar 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Tests/Add-Bar.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Add-Bar' { 12 | It 'Produces bars from parameter' { 13 | $data = Get-Process | Select-Object -Property Name,Id,WorkingSet64 14 | $bars = Add-Bar -InputObject $data -Property WorkingSet64 -Width 50 15 | $bars | ForEach-Object { 16 | $_.PSObject.Properties | Where-Object Name -eq 'Bar' | Select-Object -ExpandProperty Name | Should Be 'Bar' 17 | } 18 | } 19 | It 'Produces bars from pipeline' { 20 | $data = Get-Process | Select-Object -Property Name,Id,WorkingSet64 21 | $bars = $data | Add-Bar -Property WorkingSet64 -Width 50 22 | $bars | ForEach-Object { 23 | $_.PSObject.Properties | Where-Object Name -eq 'Bar' | Select-Object -ExpandProperty Name | Should Be 'Bar' 24 | } 25 | } 26 | It 'Produces correct output type' { 27 | $item = Get-Process | Add-Bar -Property WorkingSet64 -Width 50 | Select-Object -First 1 28 | $item.PSTypeNames -contains 'HistogramBar' | Should Be $true 29 | } 30 | It 'Has one bar of maximum width' { 31 | $data = Get-Process | Select-Object -Property Name,Id,WorkingSet64 32 | $bars = Add-Bar -InputObject $data -Property WorkingSet64 -Width 50 33 | $bars | Where-Object { $_.Bar.Length -eq 50 } | Should Not Be $null 34 | } 35 | It 'Dies on missing property' { 36 | $data = 1..10 37 | { Add-Bar -InputObject $data -Property Value } | Should Throw 38 | $data = 11..20 39 | { $data | Add-Bar -Property Value } | Should Throw 40 | } 41 | } -------------------------------------------------------------------------------- /Tests/Expand-DateTime.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Get-ChildItem -Path "$env:BHModulePath" -Filter '*.ps1' -File | ForEach-Object { 2 | # . "$($_.FullName)" 3 | #} 4 | 5 | if ($env:PSModulePath -notlike '*Statistics*') { 6 | $env:PSModulePath = "$((Get-Item -Path "$PSScriptRoot\..").FullName);$env:PSModulePath" 7 | } 8 | 9 | Import-Module -Name Statistics -Force -ErrorAction 'Stop' 10 | 11 | Describe 'Expand-DateTime' { 12 | switch ([CultureInfo]::InstalledUICulture) { 13 | 'de-DE' { 14 | $Counter = '\Prozessor(_Total)\Prozessorzeit (%)' 15 | } 16 | 'en-US' { 17 | $Counter = '\Processor(_Total)\% Processor Time' 18 | } 19 | } 20 | It 'Works on property implicitly' { 21 | { Get-Counter -Counter $Counter | Expand-DateTime } | Should Not Throw 22 | } 23 | It 'Works on property explicitly' { 24 | { Get-Counter -Counter $Counter | Expand-DateTime -Property Timestamp } | Should Not Throw 25 | } 26 | It 'Produces the correct members' { 27 | $data = Get-Counter -Counter $Counter | Expand-DateTime 28 | { $data | Select-Object -ExpandProperty Timestamp -ErrorAction SilentlyContinue } | Should Not Throw 29 | { $data | Select-Object -ExpandProperty Value -ErrorAction SilentlyContinue } | Should Not Throw 30 | { $data | Select-Object -ExpandProperty DayOfWeek -ErrorAction SilentlyContinue } | Should Not Throw 31 | { $data | Select-Object -ExpandProperty Year -ErrorAction SilentlyContinue } | Should Not Throw 32 | { $data | Select-Object -ExpandProperty Month -ErrorAction SilentlyContinue } | Should Not Throw 33 | { $data | Select-Object -ExpandProperty Hour -ErrorAction SilentlyContinue } | Should Not Throw 34 | } 35 | It 'Throws on missing property' { 36 | { Get-Counter -Counter $Counter | Expand-DateTime -Property Timestamp2 } | Should Throw 37 | } 38 | } -------------------------------------------------------------------------------- /Statistics/Statistics.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | RootModule = 'Statistics.psm1' 3 | ModuleVersion = '1.2.0' 4 | GUID = 'd5add589-39c5-4f5a-a200-ba8258085bc9' 5 | Author = 'Nicholas Dille' 6 | # CompanyName = '' 7 | Copyright = '(c) 2017 Nicholas Dille. All rights reserved.' 8 | Description = 'Statistical analysis of data in the console window. For example this module can generate a histogram (Get-Histogram) and visualize it (Add-Bar). It also provides several statistical properties of the input data (Measure-Object and Show-Measurement). Using Get-SlidingAverage, data can be analyzed in a pipeline in real-time.' 9 | PowerShellVersion = '5.0' 10 | FunctionsToExport = @('Add-Bar','ConvertFrom-PerformanceCounter','ConvertFrom-PrimitiveType','Expand-DateTime','Get-Histogram','Get-InterarrivalTime','Get-SlidingAverage','Get-WeightedValue','Measure-Group','Measure-Object','Show-Measurement') 11 | CmdletsToExport = '' 12 | VariablesToExport = '' 13 | AliasesToExport = @('ab','cfpc','cfpt','edt','gh','giat','gsa','gwv','mg','mo','sm') 14 | FormatsToProcess = @( 15 | 'HistogramBucket.Format.ps1xml' 16 | 'HistogramBar.Format.ps1xml' 17 | ) 18 | <# RequiredModules is not working correctly 19 | RequiredModules = @( 20 | @{ 21 | ModuleName = 'CICD' 22 | ModuleVersion = '0.1.22' 23 | }, 24 | @{ 25 | ModuleName = 'PSCoverage' 26 | ModuleVersion = '0.1.39' 27 | }, 28 | @{ 29 | ModuleName = 'PSGitHub' 30 | ModuleVersion = '0.13.9' 31 | } 32 | ) 33 | #> 34 | PrivateData = @{ 35 | PSData = @{ 36 | Tags = @( 37 | 'Math' 38 | 'Mathematics' 39 | 'Statistics' 40 | 'Histogram' 41 | ) 42 | LicenseUri = 'https://github.com/nicholasdille/PowerShell-Statistics/blob/master/LICENSE' 43 | ProjectUri = 'https://github.com/nicholasdille/PowerShell-Statistics' 44 | ReleaseNotes = 'https://github.com/nicholasdille/PowerShell-Statistics/releases' 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docs/en-US/Show-Measurement.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: http://go.microsoft.com/fwlink/?LinkId=821829 4 | schema: 2.0.0 5 | --- 6 | 7 | # Show-Measurement 8 | 9 | ## SYNOPSIS 10 | Visualizes statistical data about input values 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Show-Measurement [-InputObject] [[-Width] ] [-PassThru] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | Show-Measurement relies on the overload of Measure-Object provided by this module. 20 | It visualizes the data calculated by Measure-Object on the console. 21 | 22 | ## EXAMPLES 23 | 24 | ### Example 1 25 | ``` 26 | PS C:\> Get-Process | Measure-Object -Property WorkingSet | Show-Measurement 27 | ---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| 28 | P10 29 | P25 30 | A 31 | c-----C 32 | M 33 | P75 34 | P90 35 | ---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| 36 | ``` 37 | 38 | ## PARAMETERS 39 | 40 | ### -InputObject 41 | Single object produced by Measure-Object included in this module 42 | 43 | ```yaml 44 | Type: Object 45 | Parameter Sets: (All) 46 | Aliases: 47 | 48 | Required: True 49 | Position: 0 50 | Default value: None 51 | Accept pipeline input: True (ByValue) 52 | Accept wildcard characters: False 53 | ``` 54 | 55 | ### -Width 56 | Maximum number of characters to display per line 57 | 58 | ```yaml 59 | Type: Int32 60 | Parameter Sets: (All) 61 | Aliases: 62 | 63 | Required: False 64 | Position: 1 65 | Default value: None 66 | Accept pipeline input: False 67 | Accept wildcard characters: False 68 | ``` 69 | 70 | ### -PassThru 71 | {{Fill PassThru Description}} 72 | 73 | ```yaml 74 | Type: SwitchParameter 75 | Parameter Sets: (All) 76 | Aliases: 77 | 78 | Required: False 79 | Position: Named 80 | Default value: None 81 | Accept pipeline input: False 82 | Accept wildcard characters: False 83 | ``` 84 | 85 | ## INPUTS 86 | 87 | ### System.Object 88 | 89 | ## OUTPUTS 90 | 91 | ### System.Object 92 | 93 | ## NOTES 94 | 95 | ## RELATED LINKS 96 | 97 | [Median](https://en.m.wikipedia.org/wiki/Median) 98 | 99 | [Variance](https://en.m.wikipedia.org/wiki/Variance) 100 | 101 | [Standard deviation](https://en.m.wikipedia.org/wiki/Standard_deviation) 102 | 103 | [Percentile](https://en.m.wikipedia.org/wiki/Percentile) 104 | 105 | [Confidence interval](https://en.m.wikipedia.org/wiki/Confidence_interval) 106 | -------------------------------------------------------------------------------- /docs/en-US/Add-Bar.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: 4 | schema: 2.0.0 5 | --- 6 | 7 | # Add-Bar 8 | 9 | ## SYNOPSIS 10 | Visualizes values using bars 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Add-Bar [-InputObject] [[-Property] ] [[-Width] ] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | A graphical representation help understanding data. 20 | Add-Bar adds a new member to the input objects which contain bars to visualize the size of the value relative to the maximum value 21 | 22 | ## EXAMPLES 23 | 24 | ### -------------------------- EXAMPLE 1 -------------------------- 25 | ``` 26 | Add-Bar -InputObject $Files -Property Length 27 | ``` 28 | 29 | Index lowerBound upperBound Count Bar 30 | ----- ---------- ---------- ----- --- 31 | 1 0 5242880 13 ##################### 32 | 2 5242880 10485760 31 ################################################## 33 | 3 10485760 15728640 24 ####################################### 34 | 4 15728640 20971520 14 ####################### 35 | 5 20971520 26214400 5 ######## 36 | 6 26214400 31457280 5 ######## 37 | 7 31457280 36700160 3 ##### 38 | 8 36700160 41943040 2 ### 39 | 9 41943040 47185920 3 ##### 40 | 10 47185920 52428800 1 ## 41 | 42 | ### -------------------------- EXAMPLE 2 -------------------------- 43 | ``` 44 | $Files | Add-Bar -Property Length 45 | ``` 46 | 47 | ## PARAMETERS 48 | 49 | ### -InputObject 50 | Input objects containing the relevant data 51 | 52 | ```yaml 53 | Type: Array 54 | Parameter Sets: (All) 55 | Aliases: 56 | 57 | Required: True 58 | Position: 1 59 | Default value: None 60 | Accept pipeline input: True (ByValue) 61 | Accept wildcard characters: False 62 | ``` 63 | 64 | ### -Property 65 | Property of the input objects containing the relevant data 66 | 67 | ```yaml 68 | Type: String 69 | Parameter Sets: (All) 70 | Aliases: 71 | 72 | Required: False 73 | Position: 2 74 | Default value: None 75 | Accept pipeline input: False 76 | Accept wildcard characters: False 77 | ``` 78 | 79 | ### -Width 80 | Length of the bar for the maximum value (width of the graph) 81 | 82 | ```yaml 83 | Type: Int32 84 | Parameter Sets: (All) 85 | Aliases: 86 | 87 | Required: False 88 | Position: 3 89 | Default value: 50 90 | Accept pipeline input: False 91 | Accept wildcard characters: False 92 | ``` 93 | 94 | ## INPUTS 95 | 96 | ## OUTPUTS 97 | 98 | ### HistogramBar[] 99 | 100 | ## NOTES 101 | 102 | ## RELATED LINKS 103 | 104 | -------------------------------------------------------------------------------- /Statistics/Add-Bar.ps1: -------------------------------------------------------------------------------- 1 | function Add-Bar { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory, ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $InputObject 8 | , 9 | [Parameter()] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property = 'Count' 13 | , 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [int] 17 | $Width = $( if ($Host.UI.RawUI.MaxWindowSize.Width) { $Host.UI.RawUI.MaxWindowSize.Width - 30 } else { 50 } ) 18 | ) 19 | 20 | Begin { 21 | Write-Verbose ('[{0}] Initializing' -f $MyInvocation.MyCommand) 22 | 23 | $ValueFromParameter = $PSBoundParameters.ContainsKey('InputObject') 24 | $Data = New-Object -TypeName System.Collections.ArrayList 25 | } 26 | 27 | Process { 28 | if ($ValueFromParameter) { 29 | $Data = $InputObject 30 | foreach ($_ in $Data) { 31 | if (-Not (Get-Member -InputObject $_ -MemberType Properties -Name $Property)) { 32 | throw ('Input object does not contain a property called <{0}>.' -f $Property) 33 | } 34 | } 35 | 36 | } else { 37 | Write-Verbose ('[{0}] Processing {1} items' -f $MyInvocation.MyCommand, $InputObject.Length) 38 | 39 | $InputObject | ForEach-Object { 40 | if (-Not (Get-Member -InputObject $_ -MemberType Properties -Name $Property)) { 41 | throw ('Input object does not contain a property called <{0}>.' -f $Property) 42 | } 43 | [void]$Data.Add($_) 44 | } 45 | } 46 | } 47 | 48 | End { 49 | Write-Verbose ('[{0}] Adding bars for width {1}' -f $MyInvocation.MyCommand, $Width) 50 | 51 | $Count = $Data | Microsoft.PowerShell.Utility\Measure-Object -Maximum -Property $Property | Select-Object -ExpandProperty Maximum 52 | Write-Debug ('[{0}] Maximum value is {1}. This value will be {2} characters long.' -f $MyInvocation.MyCommand, $Count, $Width) 53 | 54 | $Bars = foreach ($_ in $Data) { 55 | $RelativeCount = [math]::Round($_.$Property / $Count * $Width, 0) 56 | Write-Debug ('[{0}] Value of {1} will be displayed using {2} characters.' -f $MyInvocation.MyCommand, $_.Property, $RelativeCount) 57 | 58 | Write-Debug ('[{0}] Adding member to input object.' -f $MyInvocation.MyCommand) 59 | $Item = $_ | Select-Object -Property Index,Count,$Property | Add-Member -MemberType NoteProperty -Name Bar -Value ('#' * $RelativeCount) -PassThru 60 | 61 | Write-Debug ('[{0}] Adding type name to output object.' -f $MyInvocation.MyCommand) 62 | $Item.PSTypeNames.Insert(0, 'HistogramBar') 63 | 64 | Write-Debug ('[{0}] Returning output object.' -f $MyInvocation.MyCommand) 65 | $Item 66 | } 67 | 68 | Write-Debug ('[{0}] Returning input objects with bars.' -f $MyInvocation.MyCommand) 69 | $Bars 70 | } 71 | } 72 | 73 | New-Alias -Name ab -Value Add-Bar -Force -------------------------------------------------------------------------------- /docs/en-US/Get-Histogram.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: https://en.wikipedia.org/wiki/Histogram 4 | schema: 2.0.0 5 | --- 6 | 7 | # Get-Histogram 8 | 9 | ## SYNOPSIS 10 | Visualizes values using bars 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Get-Histogram -InputObject -Property [-Minimum ] [-Maximum ] 16 | [-BucketWidth ] [-BucketCount ] 17 | ``` 18 | 19 | ## DESCRIPTION 20 | A graphical representation help understanding data. 21 | Add-Bar adds a new member to the input objects which contain bars to visualize the size of the value relative to the maximum value 22 | 23 | ## EXAMPLES 24 | 25 | ### -------------------------- EXAMPLE 1 -------------------------- 26 | ``` 27 | Add-Bar -InputObject $Files -Property Length 28 | ``` 29 | 30 | Index lowerBound upperBound Count Bar 31 | ----- ---------- ---------- ----- --- 32 | 1 0 5242880 13 ##################### 33 | 2 5242880 10485760 31 ################################################## 3 10485760 15728640 24 ####################################### 34 | 4 15728640 20971520 14 ####################### 35 | 5 20971520 26214400 5 ######## 36 | 6 26214400 31457280 5 ######## 37 | 7 31457280 36700160 3 ##### 38 | 8 36700160 41943040 2 ### 39 | 9 41943040 47185920 3 ##### 40 | 10 47185920 52428800 1 ## 41 | 42 | ### -------------------------- EXAMPLE 2 -------------------------- 43 | ``` 44 | $Files | Add-Bar -Property Length 45 | ``` 46 | 47 | ## PARAMETERS 48 | 49 | ### -BucketCount 50 | {{Fill BucketCount Description}} 51 | 52 | ```yaml 53 | Type: Single 54 | Parameter Sets: (All) 55 | Aliases: Count 56 | 57 | Required: False 58 | Position: Named 59 | Default value: None 60 | Accept pipeline input: False 61 | Accept wildcard characters: False 62 | ``` 63 | 64 | ### -BucketWidth 65 | {{Fill BucketWidth Description}} 66 | 67 | ```yaml 68 | Type: Single 69 | Parameter Sets: (All) 70 | Aliases: Width 71 | 72 | Required: False 73 | Position: Named 74 | Default value: None 75 | Accept pipeline input: False 76 | Accept wildcard characters: False 77 | ``` 78 | 79 | ### -InputObject 80 | {{Fill InputObject Description}} 81 | 82 | ```yaml 83 | Type: Array 84 | Parameter Sets: (All) 85 | Aliases: 86 | 87 | Required: True 88 | Position: Named 89 | Default value: None 90 | Accept pipeline input: True (ByValue) 91 | Accept wildcard characters: False 92 | ``` 93 | 94 | ### -Maximum 95 | {{Fill Maximum Description}} 96 | 97 | ```yaml 98 | Type: Single 99 | Parameter Sets: (All) 100 | Aliases: 101 | 102 | Required: False 103 | Position: Named 104 | Default value: None 105 | Accept pipeline input: False 106 | Accept wildcard characters: False 107 | ``` 108 | 109 | ### -Minimum 110 | {{Fill Minimum Description}} 111 | 112 | ```yaml 113 | Type: Single 114 | Parameter Sets: (All) 115 | Aliases: 116 | 117 | Required: False 118 | Position: Named 119 | Default value: None 120 | Accept pipeline input: False 121 | Accept wildcard characters: False 122 | ``` 123 | 124 | ### -Property 125 | {{Fill Property Description}} 126 | 127 | ```yaml 128 | Type: String 129 | Parameter Sets: (All) 130 | Aliases: 131 | 132 | Required: True 133 | Position: Named 134 | Default value: None 135 | Accept pipeline input: False 136 | Accept wildcard characters: False 137 | ``` 138 | 139 | ## INPUTS 140 | 141 | ## OUTPUTS 142 | 143 | ### HistogramBar[] 144 | 145 | ## NOTES 146 | 147 | ## RELATED LINKS 148 | 149 | [Histogram](https://en.wikipedia.org/wiki/Histogram) 150 | 151 | -------------------------------------------------------------------------------- /Statistics/Show-Measurement.ps1: -------------------------------------------------------------------------------- 1 | function Show-Measurement { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory)] 5 | [ValidateNotNullOrEmpty()] 6 | [object] 7 | $InputObject 8 | , 9 | [Parameter()] 10 | [ValidateNotNullOrEmpty()] 11 | [int] 12 | $Width = $( if ($Host.UI.RawUI.MaxWindowSize.Width) { $Host.UI.RawUI.MaxWindowSize.Width - 10 } else { 90 } ) 13 | , 14 | [switch] 15 | $PassThru 16 | ) 17 | 18 | Process { 19 | #region Generate visualization of measurements 20 | $AvgSubDevIndex = [math]::Round(($InputObject.Average - $InputObject.StandardDeviation) / $InputObject.Maximum * $Width, 0) 21 | $AvgIndex = [math]::Round( $InputObject.Average / $InputObject.Maximum * $Width, 0) 22 | $AvgAddDevIndex = [math]::Round(($InputObject.Average + $InputObject.StandardDeviation) / $InputObject.Maximum * $Width, 0) 23 | $AvgSubConfIndex = [math]::Round(($InputObject.Average - $InputObject.Confidence95) / $InputObject.Maximum * $Width, 0) 24 | $AvgAddConfIndex = [math]::Round(($InputObject.Average + $InputObject.Confidence95) / $InputObject.Maximum * $Width, 0) 25 | $MedIndex = [math]::Round( $InputObject.Median / $InputObject.Maximum * $Width, 0) 26 | $P10Index = [math]::Round( $InputObject.Percentile10 / $InputObject.Maximum * $Width, 0) 27 | $P25Index = [math]::Round( $InputObject.Percentile25 / $InputObject.Maximum * $Width, 0) 28 | $P75Index = [math]::Round( $InputObject.Percentile75 / $InputObject.Maximum * $Width, 0) 29 | $P90Index = [math]::Round( $InputObject.Percentile90 / $InputObject.Maximum * $Width, 0) 30 | $P25SubTukIndex = [math]::Round(($InputObject.Percentile25 - $InputObject.TukeysRange) / $InputObject.Maximum * $Width, 0) 31 | $P75AddTukIndex = [math]::Round(($InputObject.Percentile75 + $InputObject.TukeysRange) / $InputObject.Maximum * $Width, 0) 32 | 33 | Write-Debug "P10=$P10Index P25=$P25Index A=$AvgIndex M=$MedIndex sA=$AvgSubDevIndex As=$AvgAddDevIndex cA=$AvgSubConfIndex aC=$AvgAddConfIndex o=$P25SubTukIndex O=$P75AddTukIndex P75=$P75Index P90=$P90Index" 34 | 35 | $graph = @() 36 | $graph += 'Range : ' + '---------|' * ($Width / 10) 37 | $graph += '10% Percentile : ' + ' ' * $P10Index + 'P10' 38 | $graph += '25% Percentile : ' + ' ' * $P25Index + 'P25' 39 | $graph += 'Average : ' + ' ' * $AvgIndex + 'A' 40 | $graph += 'Standard Deviation: ' + (New-RangeString -Width $Width -LeftIndex $AvgSubDevIndex -RightIndex $AvgAddDevIndex -LeftIndicator 's' -RightIndicator 'S') 41 | $graph += '95% Confidence : ' + (New-RangeString -Width $Width -LeftIndex $AvgSubConfIndex -RightIndex $AvgAddConfIndex -LeftIndicator 'c' -RightIndicator 'C') 42 | $graph += 'Tukeys Range : ' + (New-RangeString -Width $Width -LeftIndex $P25SubTukIndex -RightIndex $P75AddTukIndex -LeftIndicator 'o' -RightIndicator 'O') 43 | $graph += 'Median : ' + ' ' * $MedIndex + 'M' 44 | $graph += '75% Percentile : ' + ' ' * $P75Index + 'P75' 45 | $graph += '90% Percentile : ' + ' ' * $P90Index + 'P90' 46 | $graph += 'Range : ' + '---------|' * ($Width / 10) 47 | #endregion 48 | 49 | #region Return graph 50 | if ($PassThru) { 51 | $InputObject 52 | } 53 | Write-Host ($graph -join "`n") 54 | #endregion 55 | } 56 | } 57 | 58 | New-Alias -Name sm -Value Show-Measurement -Force -------------------------------------------------------------------------------- /Statistics/Get-Histogram.ps1: -------------------------------------------------------------------------------- 1 | function Get-Histogram { 2 | [CmdletBinding(DefaultParameterSetName='BucketCount')] 3 | Param( 4 | [Parameter(Mandatory)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $Data 8 | , 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property 13 | , 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [float] 17 | $Minimum 18 | , 19 | [Parameter()] 20 | [ValidateNotNullOrEmpty()] 21 | [float] 22 | $Maximum 23 | , 24 | [Parameter()] 25 | [ValidateNotNullOrEmpty()] 26 | [Alias('Width')] 27 | [float] 28 | $BucketWidth = 1 29 | , 30 | [Parameter()] 31 | [ValidateNotNullOrEmpty()] 32 | [Alias('Count')] 33 | [float] 34 | $BucketCount 35 | ) 36 | 37 | Process { 38 | Write-Verbose ('[{0}] Building histogram' -f $MyInvocation.MyCommand) 39 | 40 | Write-Debug ('[{0}] Retrieving measurements from upstream cmdlet for {1} values' -f $MyInvocation.MyCommand, $Data.Count) 41 | Write-Progress -Activity 'Measuring data' 42 | $Stats = $Data | Microsoft.PowerShell.Utility\Measure-Object -Minimum -Maximum -Property $Property 43 | 44 | if (-Not $PSBoundParameters.ContainsKey('Minimum')) { 45 | $Minimum = $Stats.Minimum 46 | Write-Debug ('[{0}] Minimum value not specified. Using smallest value ({1}) from input data.' -f $MyInvocation.MyCommand, $Minimum) 47 | } 48 | if (-Not $PSBoundParameters.ContainsKey('Maximum')) { 49 | $Maximum = $Stats.Maximum 50 | Write-Debug ('[{0}] Maximum value not specified. Using largest value ({1}) from input data.' -f $MyInvocation.MyCommand, $Maximum) 51 | } 52 | if (-Not $PSBoundParameters.ContainsKey('BucketCount')) { 53 | $BucketCount = [math]::Ceiling(($Maximum - $Minimum) / $BucketWidth) 54 | Write-Debug ('[{0}] Bucket count not specified. Calculated {1} buckets from width of {2}.' -f $MyInvocation.MyCommand, $BucketCount, $BucketWidth) 55 | } 56 | if ($BucketCount -gt 100) { 57 | Write-Warning ('[{0}] Generating {1} buckets' -f $MyInvocation.MyCommand, $BucketCount) 58 | } 59 | 60 | Write-Debug ('[{0}] Building buckets using: Minimum=<{1}> Maximum=<{2}> BucketWidth=<{3}> BucketCount=<{4}>' -f $MyInvocation.MyCommand, $Minimum, $Maximum, $BucketWidth, $BucketCount) 61 | Write-Progress -Activity 'Creating buckets' 62 | $OverallCount = 0 63 | $Buckets = 1..$BucketCount | ForEach-Object { 64 | [pscustomobject]@{ 65 | Index = $_ 66 | lowerBound = $Minimum + ($_ - 1) * $BucketWidth 67 | upperBound = $Minimum + $_ * $BucketWidth 68 | Count = 0 69 | RelativeCount = 0 70 | Group = New-Object -TypeName System.Collections.ArrayList 71 | PSTypeName = 'HistogramBucket' 72 | } 73 | } 74 | 75 | Write-Debug ('[{0}] Building histogram' -f $MyInvocation.MyCommand) 76 | $DataIndex = 1 77 | foreach ($_ in $Data) { 78 | $Value = $_.$Property 79 | 80 | Write-Progress -Activity 'Filling buckets' -PercentComplete ($DataIndex / $Data.Count * 100) 81 | 82 | if ($Value -ge $Minimum -and $Value -le $Maximum) { 83 | $BucketIndex = [math]::Floor(($Value - $Minimum) / $BucketWidth) 84 | if ($BucketIndex -lt $Buckets.Length) { 85 | $Buckets[$BucketIndex].Count += 1 86 | [void]$Buckets[$BucketIndex].Group.Add($_) 87 | $OverallCount += 1 88 | } 89 | } 90 | 91 | ++$DataIndex 92 | } 93 | 94 | Write-Debug ('[{0}] Adding relative count' -f $MyInvocation.MyCommand) 95 | foreach ($_ in $Buckets) { 96 | $_.RelativeCount = if ($OverallCount -gt 0) { $_.Count / $OverallCount } else { 0 } 97 | } 98 | 99 | Write-Debug ('[{0}] Returning histogram' -f $MyInvocation.MyCommand) 100 | $Buckets 101 | } 102 | } 103 | 104 | New-Alias -Name gh -Value Get-Histogram -Force -------------------------------------------------------------------------------- /Statistics/Measure-Object.ps1: -------------------------------------------------------------------------------- 1 | function Measure-Object { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory)] 5 | [ValidateNotNullOrEmpty()] 6 | [array] 7 | $Data 8 | , 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $Property 13 | ) 14 | 15 | Process { 16 | #region Percentiles require sorted data 17 | $Data = $Data | Sort-Object -Property $Property 18 | #endregion 19 | 20 | #region Grab basic measurements from upstream Measure-Object 21 | $Stats = $Data | Microsoft.PowerShell.Utility\Measure-Object -Property $Property -Minimum -Maximum -Sum -Average 22 | #endregion 23 | 24 | #region Calculate median 25 | Write-Debug ('[{0}] Number of data items is <{1}>' -f $MyInvocation.MyCommand.Name, $Data.Count) 26 | if ($Data.Count % 2 -eq 0) { 27 | Write-Debug ('[{0}] Even number of data items' -f $MyInvocation.MyCommand.Name) 28 | 29 | $MedianIndex = ($Data.Count / 2) - 1 30 | Write-Debug ('[{0}] Index of Median is <{1}>' -f $MyInvocation.MyCommand.Name, $MedianIndex) 31 | 32 | $LowerMedian = $Data[$MedianIndex] | Select-Object -ExpandProperty $Property 33 | $UpperMedian = $Data[$MedianIndex + 1] | Select-Object -ExpandProperty $Property 34 | Write-Debug ('[{0}] Lower Median is <{1}> and upper Median is <{2}>' -f $MyInvocation.MyCommand.Name, $LowerMedian, $UpperMedian) 35 | 36 | $Median = ([double]$LowerMedian + [double]$UpperMedian) / 2 37 | Write-Debug ('[{0}] Average of lower and upper Median is <{1}>' -f $MyInvocation.MyCommand.Name, $Median) 38 | 39 | } else { 40 | Write-Debug ('[{0}] Odd number of data items' -f $MyInvocation.MyCommand.Name) 41 | 42 | $MedianIndex = [math]::Ceiling(($Data.Count - 1) / 2) 43 | Write-Debug ('[{0}] Index of Median is <{1}>' -f $MyInvocation.MyCommand.Name, $MedianIndex) 44 | 45 | $Median = $Data[$MedianIndex] | Select-Object -ExpandProperty $Property 46 | Write-Debug ('[{0}] Median is <{1}>' -f $MyInvocation.MyCommand.Name, $Median) 47 | } 48 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'Median' -Value $Median 49 | #endregion 50 | 51 | #region Calculate variance 52 | $Variance = 0 53 | foreach ($_ in $Data) { 54 | $Variance += [math]::Pow($_.$Property - $Stats.Average, 2) / $Stats.Count 55 | } 56 | $Variance /= $Stats.Count 57 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'Variance' -Value $Variance 58 | #endregion 59 | 60 | #region Calculate standard deviation 61 | $StandardDeviation = [math]::Sqrt($Stats.Variance) 62 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'StandardDeviation' -Value $StandardDeviation 63 | #endregion 64 | 65 | #region Calculate percentiles 66 | $Percentile10Index = [math]::Ceiling(10 / 100 * $Data.Count) 67 | $Percentile25Index = [math]::Ceiling(25 / 100 * $Data.Count) 68 | $Percentile75Index = [math]::Ceiling(75 / 100 * $Data.Count) 69 | $Percentile90Index = [math]::Ceiling(90 / 100 * $Data.Count) 70 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'Percentile10' -Value $Data[$Percentile10Index].$Property 71 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'Percentile25' -Value $Data[$Percentile25Index].$Property 72 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'Percentile75' -Value $Data[$Percentile75Index].$Property 73 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'Percentile90' -Value $Data[$Percentile90Index].$Property 74 | #endregion 75 | 76 | #region Calculate Tukey's range for outliers 77 | $TukeysOutlier = 1.5 78 | $TukeysRange = $TukeysOutlier * ($Stats.Percentile75 - $Stats.Percentile25) 79 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name TukeysRange -Value $TukeysRange 80 | #endregion 81 | 82 | #region Calculate confidence intervals 83 | $z = @{ 84 | '90' = 1.645 85 | '95' = 1.96 86 | '98' = 2.326 87 | '99' = 2.576 88 | } 89 | $Confidence95 = $z.95 * $Stats.StandardDeviation / [math]::Sqrt($Stats.Count) 90 | Add-Member -InputObject $Stats -MemberType NoteProperty -Name 'Confidence95' -Value $Confidence95 91 | #endregion 92 | 93 | #region Return measurements 94 | $Stats 95 | #endregion 96 | } 97 | } 98 | 99 | New-Alias -Name mo -Value Measure-Object -Force -------------------------------------------------------------------------------- /docs/en-US/Measure-Object.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: Statistics-help.xml 3 | online version: http://go.microsoft.com/fwlink/?LinkId=821829 4 | schema: 2.0.0 5 | --- 6 | 7 | # Measure-Object 8 | 9 | ## SYNOPSIS 10 | Overload of the official cmdlet to provide statistical insights Calculates the numeric properties of objects, and the characters, words, and lines in string objects, such as files of text. 11 | 12 | ## SYNTAX 13 | 14 | ``` 15 | Measure-Object -InputObject [-Property] 16 | ``` 17 | 18 | ## DESCRIPTION 19 | This cmdlet overloads the official implementation and adds several statistical value to the resulting object. 20 | This includes the median, several percentiles as well as the 95% confidence interval. 21 | 22 | The Measure-Object cmdlet calculates the property values of certain types of object. 23 | Measure-Object performs three types of measurements, depending on the parameters in the command. 24 | 25 | The Measure-Object cmdlet performs calculations on the property values of objects. 26 | It can count objects and calculate the minimum, maximum, sum, and average of the numeric values. 27 | For text objects, it can count and calculate the number of lines, words, and characters. 28 | 29 | ## EXAMPLES 30 | 31 | ### Example 1: Display memory usage of processes 32 | ``` 33 | PS C:\>Get-Process | Measure-Object -Property WorkingSet 34 | ``` 35 | 36 | This command visualizes the memory usage of processes currently running on the local machine. 37 | 38 | ### Example 1: Count the files and folders in a directory 39 | ``` 40 | PS C:\>Get-ChildItem | Measure-Object 41 | ``` 42 | 43 | This command counts the files and folders in the current directory. 44 | 45 | ### Example 2: Measure the files in a directory 46 | ``` 47 | PS C:\>Get-ChildItem | Measure-Object -Property length -Minimum -Maximum -Average 48 | ``` 49 | 50 | This command displays the minimum, maximum, and sum of the sizes of all files in the current directory, and the average size of a file in the directory. 51 | 52 | ### Example 3: Measure text in a text file 53 | ``` 54 | PS C:\>Get-Content C:\test.txt | Measure-Object -Character -Line -Word 55 | ``` 56 | 57 | This command displays the number of characters, words, and lines in the Text.txt file. 58 | 59 | ### Example 4: Measure computer processes 60 | ``` 61 | PS C:\>Get-Process | Measure-Object -Property workingset -Minimum -Maximum -Average 62 | ``` 63 | 64 | This command displays the minimum, maximum, and average sizes of the working sets of the processes on the computer. 65 | 66 | ### Example 5: Measure the contents of a CSV file 67 | ``` 68 | PS C:\>Import-Csv d:\test\serviceyrs.csv | Measure-Object -Property years -Minimum -Maximum -Average 69 | ``` 70 | 71 | This command calculates the average years of service of the employees of a company. 72 | 73 | The ServiceYrs.csv file is a CSV file that contains the employee number and years of service of each employee. 74 | The first row in the table is a header row of EmpNo, Years. 75 | 76 | When you use Import-Csv to import the file, the result is a PSCustomObject with note properties of EmpNo and Years. 77 | You can use Measure-Object to calculate the values of these properties, just like any other property of an object. 78 | 79 | ### Example 6: Measure Boolean values 80 | ``` 81 | PS C:\>Get-ChildItem | Measure-Object -Property psiscontainer -Max -Sum -Min -Average 82 | Count : 126 83 | Average : 0.0634920634920635 84 | Sum : 8 85 | Maximum : 1 86 | Minimum : 0 87 | Property : PSIsContainer 88 | ``` 89 | 90 | This example demonstrates how the Measure-Object can measure Boolean values. 91 | In this case, it uses the PSIsContainer Boolean property to measure the incidence of folders (vs. 92 | files) in the current directory. 93 | 94 | ## PARAMETERS 95 | 96 | ### -InputObject 97 | Specifies the objects to be measured. 98 | 99 | Specifies the objects to be measured. 100 | Enter a variable that contains the objects, or type a command or expression that gets the objects. 101 | 102 | When you use the InputObject parameter with Measure-Object , instead of piping command results to Measure-Object , the InputObject value-even if the value is a collection that is the result of a command, such as \`-InputObject (Get-Process)\`-is treated as a single object. 103 | Because InputObject cannot return individual properties from an array or collection of objects, it is recommended that if you use Measure-Object to measure a collection of objects for those objects that have specific values in defined properties, you use Measure-Object in the pipeline, as shown in the examples in this topic. 104 | 105 | ```yaml 106 | Type: Array 107 | Parameter Sets: (All) 108 | Aliases: 109 | 110 | Required: True 111 | Position: Named 112 | Default value: None 113 | Accept pipeline input: True (ByValue) 114 | Accept wildcard characters: False 115 | ``` 116 | 117 | ### -Property 118 | Specifies the numeric property to measure 119 | 120 | Specifies one or more numeric properties to measure. 121 | The default is the Count property of the object. 122 | 123 | ```yaml 124 | Type: String 125 | Parameter Sets: (All) 126 | Aliases: 127 | 128 | Required: True 129 | Position: 0 130 | Default value: None 131 | Accept pipeline input: False 132 | Accept wildcard characters: False 133 | ``` 134 | 135 | ## INPUTS 136 | 137 | ### System.Array 138 | 139 | ### System.Management.Automation.PSObject 140 | You can pipe objects to Measure-Object. 141 | 142 | ### System.Management.Automation.PSObject 143 | You can pipe objects to Measure-Object . 144 | 145 | ## OUTPUTS 146 | 147 | ### System.Object 148 | 149 | ### Microsoft.PowerShell.Commands.GenericMeasureInfo, Microsoft.PowerShell.Commands.TextMeasureInfo, Microsoft.PowerShell.Commands.GenericObjectMeasureInfo 150 | If you use the Word parameter, Measure-Object returns a TextMeasureInfo object. 151 | Otherwise, it returns a GenericMeasureInfo object. 152 | 153 | ## NOTES 154 | ## RELATED LINKS 155 | 156 | [Median](https://en.m.wikipedia.org/wiki/Median) 157 | 158 | [Variance](https://en.m.wikipedia.org/wiki/Variance) 159 | 160 | [Standard deviation](https://en.m.wikipedia.org/wiki/Standard_deviation) 161 | 162 | [Percentile](https://en.m.wikipedia.org/wiki/Percentile) 163 | 164 | [Confidence interval](https://en.m.wikipedia.org/wiki/Confidence_interval) 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | | AppVeyor | Coveralls | Download | 2 | | :------: | :-------: | :------: | 3 | | [![Build status](https://ci.appveyor.com/api/projects/status/e56ra8c3q1jtc19o?svg=true)](https://ci.appveyor.com/project/nicholasdille/powershell-statistics) | [![Coverage Status](https://coveralls.io/repos/github/nicholasdille/PowerShell-Statistics/badge.svg?branch=master)](https://coveralls.io/github/nicholasdille/PowerShell-Statistics?branch=master) | [![Download](https://img.shields.io/badge/powershellgallery-Statistics-blue.svg)](https://www.powershellgallery.com/packages/Statistics/) 4 | 5 | # Introduction 6 | 7 | Statistical analysis 8 | 9 | # TODO 10 | 11 | - Use `Update-TypeData` 12 | - Display values in `Show-Measurement`... include minimum and maximum 13 | - Limit displayed range in `Show-Measurement` 14 | - Check handling of negative values 15 | - More tests 16 | - Get-SlidingAverage 17 | - Output data similar to `Group-Object` by adding properties `Property`, `Group` and `Average` 18 | - Filter performance counters from `(Get-Counter).CounterSamples` 19 | - Progress bar 20 | - Implement in all cmdlets 21 | - Support for child bars 22 | - Performance improvements by using ArrayList instead of `+=` 23 | - Provide predefined buckets to `Get-Histogram` 24 | 25 | # Warning 26 | 27 | **Many cmdlets contained in this modules operate directly on the input objects and add new properties to them. This is a design decision to prevent excessive memory usage caused by copying the input data.** 28 | 29 | # Histograms 30 | 31 | Create a histogram from the currently running processes using `Get-Histogram`. The WorkingSet will be used to express the amount of memory used by the processes. It makes sense to specify the bucket size (`-BucketWidth`) as well as the number of buckets (`-BucketCount`). 32 | 33 | ```powershell 34 | PS C:\> $Processes = Get-Process 35 | PS C:\> $Histogram = $Processes | Get-Histogram -Property WorkingSet64 -BucketWidth 50mb -BucketCount 10 36 | PS C:\> $Histogram 37 | 38 | Index Count 39 | ----- ----- 40 | 1 75 41 | 2 15 42 | 3 9 43 | 4 2 44 | 5 0 45 | 6 2 46 | 7 1 47 | 8 1 48 | 9 1 49 | 10 2 50 | ``` 51 | 52 | The histogram is visualized using `Add-Bar`. It adds a new property to the input objects containing the bar. Note that the width is predefined to match the current console window. 53 | 54 | ```powershell 55 | PS C:\> $Histogram | Add-Bar 56 | 57 | Index Count Bar 58 | ----- ----- --- 59 | 1 75 #################################################################################################### 60 | 2 15 #################### 61 | 3 9 ############ 62 | 4 2 ### 63 | 5 0 64 | 6 2 ### 65 | 7 1 # 66 | 8 1 # 67 | 9 1 # 68 | 10 2 ### 69 | ``` 70 | 71 | # Statistical analysis 72 | 73 | In addition to value distribution, statistics has a lot more to offer. This module overloads the cmdlet `Measure-Object` and adds many properties like the median and the standard deviation. 74 | 75 | ```powershell 76 | PS C:\> $Processes | Measure-Object -Property WorkingSet64 77 | 78 | 79 | Median : 24731648 80 | Variance : 1,86476251813904E+16 81 | StandardDeviation : 136556307,731977 82 | Percentile10 : 6496256 83 | Percentile25 : 12095488 84 | Percentile75 : 92958720 85 | Percentile90 : 190754816 86 | Confidence95 : 25519460,826598 87 | Count : 110 88 | Average : 76195169,7454546 89 | Sum : 8381468672 90 | Maximum : 875040768 91 | Minimum : 4096 92 | Property : WorkingSet64 93 | ``` 94 | 95 | Although those values are very interesting, visualizing them using `Show-Measurement` helps understanding your data set. 96 | 97 | ```powershell 98 | PS C:\> $Processes | Measure-Object -Property WorkingSet64 | Show-Measurement 99 | ---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| 100 | P10 101 | P25 102 | A 103 | c----C 104 | M 105 | P75 106 | P90 107 | ---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| 108 | PS C:\> 109 | ``` 110 | 111 | # Simple data 112 | 113 | In case you have input data as primitive type (e.g. [int]), use can use `ConvertFrom-PrimitiveType` to construct a complex (yet still simple) type containing the values. The output can be used for any cmdlet described above. 114 | 115 | ```powershell 116 | PS C:\> 1..10 | ConvertFrom-PrimitiveType 117 | 118 | Value 119 | ----- 120 | 1 121 | 2 122 | 3 123 | 4 124 | 5 125 | 6 126 | 7 127 | 8 128 | 9 129 | 10 130 | ``` 131 | 132 | # Analyzing performance counters 133 | 134 | Performance counters are retrieved using the builtin cmdlet `Get-Counter`. Unfortunately, this cmdlet wraps the samples in a separate property. `ConvertFrom-PerformanceCounter` changes the structure of the input data to make it easier to process. The cmdlet can be used for stream processing in a pipeline. 135 | 136 | ```powershell 137 | PS C:\> Get-Counter -Counter '\Processor(_Total)\% Processor Time' -SampleInterval 1 -MaxSamples 10 | ConvertFrom-PerformanceCounter -Instance _total 138 | 139 | Timestamp Value 140 | --------- ----- 141 | 29.03.2017 14:29:46 2,97703720584355 142 | 29.03.2017 14:29:47 3,06092596747546 143 | 29.03.2017 14:29:48 6,49145039193071 144 | 29.03.2017 14:29:49 7,9961263543842 145 | 29.03.2017 14:29:50 5,11584502920018 146 | 29.03.2017 14:29:51 4,63986180903145 147 | 29.03.2017 14:29:52 4,53201559488423 148 | 29.03.2017 14:29:53 1,77517662636473 149 | 29.03.2017 14:29:54 10,1188887197758 150 | 29.03.2017 14:29:55 4,1137771992306 151 | ``` 152 | 153 | The individual values do not tell you enough because they may be peaking once in a while. `Get-SlidingAverage` calculates an average over a window of the specified size: 154 | 155 | ```powershell 156 | PS C:\> Get-Counter -Counter '\Processor(_Total)\% Processor Time' -SampleInterval 1 -MaxSamples 10 | ConvertFrom-PerformanceCounter -Instance _total | Get-SlidingAverage -Property Value -Size 5 157 | 0,999077477590933 158 | 0,954436964202299 159 | 0,572272227101394 160 | 0,572272227101394 161 | 0,417360277344085 162 | 0,797367872038486 163 | ``` 164 | 165 | # Time series 166 | 167 | In contrast to reading samples at regular intervals (as seen above for performance counters), you sometime obtain values at irregular intervals. Analyzing the timestamps will tell you as much as the data values. For the sake of this example, let's generate sample data. The timestamp is generated randomly over the last 24 hours: 168 | 169 | ```powershell 170 | $now = Get-Date 171 | $data = 1..10 | ForEach-Object { 172 | [pscustomobject]@{ 173 | Timestamp = Get-Random -Minimum $now.AddDays(-1).Ticks -Maximum $now.Ticks 174 | Value = Get-Random -Minimum 0 -Maximum 100 175 | } 176 | } | Sort-Object -Property Timestamp 177 | ``` 178 | 179 | Let's take a closer look at the distance (interarrival time) between samples. By default, the distance is expessed in ticks but you can choose from several units using `-Unit`. 180 | 181 | ```powershell 182 | PS C:\> $data | Get-InterarrivalTime -Property Timestamp 183 | 184 | Timestamp Value InterarrivalTicks 185 | --------- ----- ----------------- 186 | 636263194123056256 30 2285541632 187 | 636263376363844864 49 182240788608 188 | 636263469245163392 21 92881318528 189 | 636263553811059072 9 84565895680 190 | 636263622795032960 42 68983973888 191 | 636263691231611392 87 68436578432 192 | 636263800435401856 28 109203790464 193 | 636263902248199552 27 101812797696 194 | 636263932075540992 69 29827341440 195 | 196 | PS C:\> $data | Get-InterarrivalTime -Property Timestamp -Unit Minutes 197 | 198 | Timestamp Value InterarrivalMinutes 199 | --------- ----- ------------------- 200 | 636263260120122752 49 21 201 | 636263337519778304 14 8 202 | 636263366516410368 49 48 203 | 636263500972027904 15 44 204 | 636263620709248256 95 19 205 | 636263635450691840 97 24 206 | 636263747658795264 44 7 207 | 636263773550362368 98 43 208 | 636263853541291392 88 13 209 | ``` 210 | 211 | The ticks-based timestamp in the examples above it impossibel to read without any conversion. This module also offers a cmdlet called `Expand-DateTime` to convert timestamps: 212 | 213 | ```powershell 214 | PS C:\> $data | Expand-DateTime -Property Timestamp 215 | 216 | Timestamp Value DayOfWeek Year Month Hour WeekOfYear 217 | --------- ----- --------- ---- ----- ---- ---------- 218 | 28.03.2017 18:34:18 23 Tuesday 2017 3 18 13 219 | 28.03.2017 19:13:38 43 Tuesday 2017 3 19 13 220 | 28.03.2017 20:42:08 53 Tuesday 2017 3 20 13 221 | 28.03.2017 21:41:23 73 Tuesday 2017 3 21 13 222 | 28.03.2017 22:28:16 9 Tuesday 2017 3 22 13 223 | 28.03.2017 22:46:47 20 Tuesday 2017 3 22 13 224 | 28.03.2017 22:50:01 75 Tuesday 2017 3 22 13 225 | 29.03.2017 01:01:26 40 Wednesday 2017 3 1 13 226 | 29.03.2017 05:11:43 55 Wednesday 2017 3 5 13 227 | 29.03.2017 09:10:39 77 Wednesday 2017 3 9 13 228 | ``` 229 | 230 | # Credits 231 | 232 | Build scripts based on [PSDeploy](https://github.com/RamblingCookieMonster/PSDeploy) by [Warren Frame](http://ramblingcookiemonster.github.io/) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------