From 66efa1df07ffb285848847127c74ad49127320ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 17:13:34 +0000 Subject: [PATCH] Bump github.com/montanaflynn/stats from 0.9.0 to 0.11.0 Bumps [github.com/montanaflynn/stats](https://github.com/montanaflynn/stats) from 0.9.0 to 0.11.0. - [Release notes](https://github.com/montanaflynn/stats/releases) - [Changelog](https://github.com/montanaflynn/stats/blob/master/CHANGELOG.md) - [Commits](https://github.com/montanaflynn/stats/compare/v0.9.0...v0.11.0) --- updated-dependencies: - dependency-name: github.com/montanaflynn/stats dependency-version: 0.11.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- .../montanaflynn/stats/.github-write-test | 1 - .../github.com/montanaflynn/stats/.gitignore | 1 - .../montanaflynn/stats/CHANGELOG.md | 79 +- .../montanaflynn/stats/DOCUMENTATION.md | 1001 ++++++++++++++++- vendor/github.com/montanaflynn/stats/Makefile | 9 +- .../github.com/montanaflynn/stats/README.md | 47 +- vendor/github.com/montanaflynn/stats/clip.go | 32 + .../stats/coefficient_of_variation.go | 31 + .../montanaflynn/stats/correlation.go | 91 +- .../montanaflynn/stats/cumulative.go | 76 ++ vendor/github.com/montanaflynn/stats/data.go | 9 +- .../github.com/montanaflynn/stats/describe.go | 4 + vendor/github.com/montanaflynn/stats/diff.go | 48 + vendor/github.com/montanaflynn/stats/ewma.go | 32 + .../github.com/montanaflynn/stats/extremes.go | 72 ++ .../montanaflynn/stats/histogram.go | 57 + .../github.com/montanaflynn/stats/interp.go | 46 + .../github.com/montanaflynn/stats/kendall.go | 57 + .../github.com/montanaflynn/stats/kurtosis.go | 70 ++ vendor/github.com/montanaflynn/stats/mean.go | 15 +- .../github.com/montanaflynn/stats/moving.go | 125 ++ vendor/github.com/montanaflynn/stats/norm.go | 6 + .../montanaflynn/stats/percentile_of_score.go | 31 + .../montanaflynn/stats/percentile_weighted.go | 69 ++ .../github.com/montanaflynn/stats/product.go | 26 + vendor/github.com/montanaflynn/stats/rank.go | 16 + .../github.com/montanaflynn/stats/rescale.go | 29 + vendor/github.com/montanaflynn/stats/rms.go | 23 + .../github.com/montanaflynn/stats/rolling.go | 65 ++ vendor/github.com/montanaflynn/stats/round.go | 28 +- vendor/github.com/montanaflynn/stats/sem.go | 24 + .../montanaflynn/stats/trimmed_mean.go | 38 + vendor/github.com/montanaflynn/stats/ttest.go | 128 +++ .../montanaflynn/stats/weighted_mean.go | 42 + .../montanaflynn/stats/winsorize.go | 50 + .../github.com/montanaflynn/stats/zscore.go | 29 + vendor/github.com/montanaflynn/stats/ztest.go | 50 + vendor/modules.txt | 2 +- 40 files changed, 2440 insertions(+), 125 deletions(-) delete mode 100644 vendor/github.com/montanaflynn/stats/.github-write-test create mode 100644 vendor/github.com/montanaflynn/stats/clip.go create mode 100644 vendor/github.com/montanaflynn/stats/coefficient_of_variation.go create mode 100644 vendor/github.com/montanaflynn/stats/cumulative.go create mode 100644 vendor/github.com/montanaflynn/stats/diff.go create mode 100644 vendor/github.com/montanaflynn/stats/ewma.go create mode 100644 vendor/github.com/montanaflynn/stats/extremes.go create mode 100644 vendor/github.com/montanaflynn/stats/histogram.go create mode 100644 vendor/github.com/montanaflynn/stats/interp.go create mode 100644 vendor/github.com/montanaflynn/stats/kendall.go create mode 100644 vendor/github.com/montanaflynn/stats/kurtosis.go create mode 100644 vendor/github.com/montanaflynn/stats/moving.go create mode 100644 vendor/github.com/montanaflynn/stats/percentile_of_score.go create mode 100644 vendor/github.com/montanaflynn/stats/percentile_weighted.go create mode 100644 vendor/github.com/montanaflynn/stats/product.go create mode 100644 vendor/github.com/montanaflynn/stats/rank.go create mode 100644 vendor/github.com/montanaflynn/stats/rescale.go create mode 100644 vendor/github.com/montanaflynn/stats/rms.go create mode 100644 vendor/github.com/montanaflynn/stats/rolling.go create mode 100644 vendor/github.com/montanaflynn/stats/sem.go create mode 100644 vendor/github.com/montanaflynn/stats/trimmed_mean.go create mode 100644 vendor/github.com/montanaflynn/stats/ttest.go create mode 100644 vendor/github.com/montanaflynn/stats/weighted_mean.go create mode 100644 vendor/github.com/montanaflynn/stats/winsorize.go create mode 100644 vendor/github.com/montanaflynn/stats/zscore.go create mode 100644 vendor/github.com/montanaflynn/stats/ztest.go diff --git a/go.mod b/go.mod index a31517f..f3dead4 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/alecthomas/kingpin/v2 v2.4.0 github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973 github.com/kubeservice-stack/common v1.9.1 - github.com/montanaflynn/stats v0.9.0 + github.com/montanaflynn/stats v0.11.0 github.com/prometheus/client_golang v1.23.2 github.com/prometheus/common v0.69.0 github.com/prometheus/exporter-toolkit v0.16.0 diff --git a/go.sum b/go.sum index 0172567..1b5a35f 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= -github.com/montanaflynn/stats v0.9.0 h1:tsBJ0RXwph9BmAuFoCmqGv6e8xa0MENQ8m0ptKq29mQ= -github.com/montanaflynn/stats v0.9.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/montanaflynn/stats v0.11.0 h1:zDghK0ZIhSGNLdZaZYob15c5fjgVnuTzv/MRZ9UJifY= +github.com/montanaflynn/stats v0.11.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= diff --git a/vendor/github.com/montanaflynn/stats/.github-write-test b/vendor/github.com/montanaflynn/stats/.github-write-test deleted file mode 100644 index 30d74d2..0000000 --- a/vendor/github.com/montanaflynn/stats/.github-write-test +++ /dev/null @@ -1 +0,0 @@ -test \ No newline at end of file diff --git a/vendor/github.com/montanaflynn/stats/.gitignore b/vendor/github.com/montanaflynn/stats/.gitignore index 75a2a3a..ba3574a 100644 --- a/vendor/github.com/montanaflynn/stats/.gitignore +++ b/vendor/github.com/montanaflynn/stats/.gitignore @@ -2,6 +2,5 @@ coverage.out coverage.txt release-notes.txt .directory -.chglog .vscode .DS_Store \ No newline at end of file diff --git a/vendor/github.com/montanaflynn/stats/CHANGELOG.md b/vendor/github.com/montanaflynn/stats/CHANGELOG.md index 580ce3e..4a82f6d 100644 --- a/vendor/github.com/montanaflynn/stats/CHANGELOG.md +++ b/vendor/github.com/montanaflynn/stats/CHANGELOG.md @@ -2,6 +2,77 @@ ## [Unreleased] + + + +## [v0.11.0] - 2026-07-13 +### Add +- Add Interp for piecewise-linear interpolation ([#121](https://github.com/montanaflynn/stats/issues/121)) +- Add Histogram with equal-width bins ([#120](https://github.com/montanaflynn/stats/issues/120)) +- Add KendallTau rank correlation coefficient ([#119](https://github.com/montanaflynn/stats/issues/119)) +- Add SEM, RMS, Product, and PercentileOfScore ([#118](https://github.com/montanaflynn/stats/issues/118)) +- Add MovingMedian, MovingMin, MovingMax, MovingSum, and EWMA ([#117](https://github.com/montanaflynn/stats/issues/117)) +- Add TrimmedMean and Winsorize robust statistics ([#116](https://github.com/montanaflynn/stats/issues/116)) +- Add Kurtosis, PopulationKurtosis, and SampleKurtosis ([#115](https://github.com/montanaflynn/stats/issues/115)) +- Add Clip and Rescale elementwise transforms ([#114](https://github.com/montanaflynn/stats/issues/114)) + + + +## [v0.10.0] - 2026-07-10 +### Add +- Add MovingAverage and MovingStdDev ([#112](https://github.com/montanaflynn/stats/issues/112)) +- Add ZScore and Rank functions ([#111](https://github.com/montanaflynn/stats/issues/111)) +- Add WeightedMean and CoefficientOfVariation ([#110](https://github.com/montanaflynn/stats/issues/110)) +- Add ArgMax, ArgMin and Range functions ([#109](https://github.com/montanaflynn/stats/issues/109)) +- Add CumulativeProduct, CumulativeMax and CumulativeMin ([#108](https://github.com/montanaflynn/stats/issues/108)) +- Add Diff and PercentChange functions ([#107](https://github.com/montanaflynn/stats/issues/107)) +- Add weighted percentile function ([#102](https://github.com/montanaflynn/stats/issues/102)) +- Add NormSample function for normal distribution sampling ([#100](https://github.com/montanaflynn/stats/issues/100)) +- Add Z-test and T-test functions ([#99](https://github.com/montanaflynn/stats/issues/99)) +- Add Spearman rank correlation function ([#98](https://github.com/montanaflynn/stats/issues/98)) + +### Fix +- Stabilize GeometricMean and add input validation +- Use math.Round to avoid ARM64 FMA fusion miscompile ([#97](https://github.com/montanaflynn/stats/issues/97)) +- Correct AutoCorrelation lag handling ([#83](https://github.com/montanaflynn/stats/issues/83)) ([#95](https://github.com/montanaflynn/stats/issues/95)) + + + +## [v0.10.0] - 2026-07-10 +### Add +- Add MovingAverage and MovingStdDev ([#112](https://github.com/montanaflynn/stats/issues/112)) +- Add ZScore and Rank functions ([#111](https://github.com/montanaflynn/stats/issues/111)) +- Add WeightedMean and CoefficientOfVariation ([#110](https://github.com/montanaflynn/stats/issues/110)) +- Add ArgMax, ArgMin and Range functions ([#109](https://github.com/montanaflynn/stats/issues/109)) +- Add CumulativeProduct, CumulativeMax and CumulativeMin ([#108](https://github.com/montanaflynn/stats/issues/108)) +- Add Diff and PercentChange functions ([#107](https://github.com/montanaflynn/stats/issues/107)) +- Add weighted percentile function ([#102](https://github.com/montanaflynn/stats/issues/102)) +- Add NormSample function for normal distribution sampling ([#100](https://github.com/montanaflynn/stats/issues/100)) +- Add Z-test and T-test functions ([#99](https://github.com/montanaflynn/stats/issues/99)) +- Add Spearman rank correlation function ([#98](https://github.com/montanaflynn/stats/issues/98)) + +### Fix +- Stabilize GeometricMean and add input validation +- Use math.Round to avoid ARM64 FMA fusion miscompile ([#97](https://github.com/montanaflynn/stats/issues/97)) +- Correct AutoCorrelation lag handling ([#83](https://github.com/montanaflynn/stats/issues/83)) ([#95](https://github.com/montanaflynn/stats/issues/95)) + + + +## [v0.9.0] - 2026-03-24 +### Add +- Add Skewness, PopulationSkewness, and SampleSkewness functions ([#91](https://github.com/montanaflynn/stats/issues/91)) + +### Fix +- Restore 100% test coverage for skewness +- Remove unused sum[4] in LinearRegression + + + +## [v0.8.2] - 2026-03-11 + + +## [v0.8.1] - 2026-03-11 + ## [v0.8.0] - 2026-03-11 ### Fix @@ -527,7 +598,13 @@ - Merge pull request [#4](https://github.com/montanaflynn/stats/issues/4) from saromanov/sample -[Unreleased]: https://github.com/montanaflynn/stats/compare/v0.8.0...HEAD +[Unreleased]: https://github.com/montanaflynn/stats/compare/v0.11.0...HEAD +[v0.11.0]: https://github.com/montanaflynn/stats/compare/v0.10.0...v0.11.0 +[v0.10.0]: https://github.com/montanaflynn/stats/compare/v0.9.0...v0.10.0 +[v0.10.0]: https://github.com/montanaflynn/stats/compare/v0.9.0...v0.10.0 +[v0.9.0]: https://github.com/montanaflynn/stats/compare/v0.8.2...v0.9.0 +[v0.8.2]: https://github.com/montanaflynn/stats/compare/v0.8.1...v0.8.2 +[v0.8.1]: https://github.com/montanaflynn/stats/compare/v0.8.0...v0.8.1 [v0.8.0]: https://github.com/montanaflynn/stats/compare/v0.7.1...v0.8.0 [v0.7.1]: https://github.com/montanaflynn/stats/compare/v0.7.0...v0.7.1 [v0.7.0]: https://github.com/montanaflynn/stats/compare/v0.6.6...v0.7.0 diff --git a/vendor/github.com/montanaflynn/stats/DOCUMENTATION.md b/vendor/github.com/montanaflynn/stats/DOCUMENTATION.md index 32ec075..0dc1c0d 100644 --- a/vendor/github.com/montanaflynn/stats/DOCUMENTATION.md +++ b/vendor/github.com/montanaflynn/stats/DOCUMENTATION.md @@ -36,18 +36,31 @@ MIT License Copyright (c) 2014-2026 Montana Flynn (Index * [Variables](#pkg-variables) +* [func ArgMax(input Float64Data) (int, error)](#ArgMax) +* [func ArgMin(input Float64Data) (int, error)](#ArgMin) * [func AutoCorrelation(data Float64Data, lags int) (float64, error)](#AutoCorrelation) * [func ChebyshevDistance(dataPointX, dataPointY Float64Data) (distance float64, err error)](#ChebyshevDistance) +* [func Clip(input Float64Data, min, max float64) ([]float64, error)](#Clip) +* [func CoefficientOfVariation(input Float64Data) (float64, error)](#CoefficientOfVariation) * [func Correlation(data1, data2 Float64Data) (float64, error)](#Correlation) * [func Covariance(data1, data2 Float64Data) (float64, error)](#Covariance) * [func CovariancePopulation(data1, data2 Float64Data) (float64, error)](#CovariancePopulation) +* [func CumulativeMax(input Float64Data) ([]float64, error)](#CumulativeMax) +* [func CumulativeMin(input Float64Data) ([]float64, error)](#CumulativeMin) +* [func CumulativeProduct(input Float64Data) ([]float64, error)](#CumulativeProduct) * [func CumulativeSum(input Float64Data) ([]float64, error)](#CumulativeSum) +* [func Diff(input Float64Data) ([]float64, error)](#Diff) +* [func EWMA(input Float64Data, alpha float64) ([]float64, error)](#EWMA) * [func Entropy(input Float64Data) (float64, error)](#Entropy) * [func EuclideanDistance(dataPointX, dataPointY Float64Data) (distance float64, err error)](#EuclideanDistance) * [func ExpGeom(p float64) (exp float64, err error)](#ExpGeom) * [func GeometricMean(input Float64Data) (float64, error)](#GeometricMean) * [func HarmonicMean(input Float64Data) (float64, error)](#HarmonicMean) +* [func Histogram(input Float64Data, bins int) ([]int, []float64, error)](#Histogram) * [func InterQuartileRange(input Float64Data) (float64, error)](#InterQuartileRange) +* [func Interp(x, xp, fp Float64Data) ([]float64, error)](#Interp) +* [func KendallTau(data1, data2 Float64Data) (float64, error)](#KendallTau) +* [func Kurtosis(input Float64Data) (float64, error)](#Kurtosis) * [func ManhattanDistance(dataPointX, dataPointY Float64Data) (distance float64, err error)](#ManhattanDistance) * [func Max(input Float64Data) (max float64, err error)](#Max) * [func Mean(input Float64Data) (float64, error)](#Mean) @@ -58,6 +71,12 @@ MIT License Copyright (c) 2014-2026 Montana Flynn (Examples +* [ArgMax](#example_ArgMax) +* [ArgMin](#example_ArgMin) * [AutoCorrelation](#example_AutoCorrelation) * [ChebyshevDistance](#example_ChebyshevDistance) +* [Clip](#example_Clip) * [Correlation](#example_Correlation) +* [CumulativeMax](#example_CumulativeMax) +* [CumulativeMin](#example_CumulativeMin) +* [CumulativeProduct](#example_CumulativeProduct) * [CumulativeSum](#example_CumulativeSum) +* [Diff](#example_Diff) +* [EWMA](#example_EWMA) * [Entropy](#example_Entropy) * [ExpGeom](#example_ExpGeom) +* [Histogram](#example_Histogram) +* [Interp](#example_Interp) +* [KendallTau](#example_KendallTau) +* [Kurtosis](#example_Kurtosis) * [LinearRegression](#example_LinearRegression) * [LoadRawData](#example_LoadRawData) * [Max](#example_Max) * [Median](#example_Median) * [Min](#example_Min) +* [MovingAverage](#example_MovingAverage) +* [MovingMax](#example_MovingMax) +* [MovingMedian](#example_MovingMedian) +* [MovingMin](#example_MovingMin) +* [MovingStdDev](#example_MovingStdDev) +* [MovingSum](#example_MovingSum) +* [PercentChange](#example_PercentChange) +* [PercentileOfScore](#example_PercentileOfScore) * [ProbGeom](#example_ProbGeom) +* [Product](#example_Product) +* [RMS](#example_RMS) +* [Range](#example_Range) +* [Rank](#example_Rank) +* [Rescale](#example_Rescale) * [Round](#example_Round) +* [SEM](#example_SEM) +* [SampleKurtosis](#example_SampleKurtosis) * [Sigmoid](#example_Sigmoid) * [SoftMax](#example_SoftMax) +* [Spearman](#example_Spearman) * [Sum](#example_Sum) +* [TrimmedMean](#example_TrimmedMean) * [VarGeom](#example_VarGeom) +* [Winsorize](#example_Winsorize) +* [ZScore](#example_ZScore) #### Package files -[correlation.go](/src/github.com/montanaflynn/stats/correlation.go) [cumulative_sum.go](/src/github.com/montanaflynn/stats/cumulative_sum.go) [data.go](/src/github.com/montanaflynn/stats/data.go) [describe.go](/src/github.com/montanaflynn/stats/describe.go) [deviation.go](/src/github.com/montanaflynn/stats/deviation.go) [distances.go](/src/github.com/montanaflynn/stats/distances.go) [doc.go](/src/github.com/montanaflynn/stats/doc.go) [entropy.go](/src/github.com/montanaflynn/stats/entropy.go) [errors.go](/src/github.com/montanaflynn/stats/errors.go) [geometric_distribution.go](/src/github.com/montanaflynn/stats/geometric_distribution.go) [legacy.go](/src/github.com/montanaflynn/stats/legacy.go) [load.go](/src/github.com/montanaflynn/stats/load.go) [max.go](/src/github.com/montanaflynn/stats/max.go) [mean.go](/src/github.com/montanaflynn/stats/mean.go) [median.go](/src/github.com/montanaflynn/stats/median.go) [min.go](/src/github.com/montanaflynn/stats/min.go) [mode.go](/src/github.com/montanaflynn/stats/mode.go) [norm.go](/src/github.com/montanaflynn/stats/norm.go) [outlier.go](/src/github.com/montanaflynn/stats/outlier.go) [percentile.go](/src/github.com/montanaflynn/stats/percentile.go) [quartile.go](/src/github.com/montanaflynn/stats/quartile.go) [ranksum.go](/src/github.com/montanaflynn/stats/ranksum.go) [regression.go](/src/github.com/montanaflynn/stats/regression.go) [round.go](/src/github.com/montanaflynn/stats/round.go) [sample.go](/src/github.com/montanaflynn/stats/sample.go) [sigmoid.go](/src/github.com/montanaflynn/stats/sigmoid.go) [softmax.go](/src/github.com/montanaflynn/stats/softmax.go) [sum.go](/src/github.com/montanaflynn/stats/sum.go) [util.go](/src/github.com/montanaflynn/stats/util.go) [variance.go](/src/github.com/montanaflynn/stats/variance.go) +[clip.go](/src/github.com/montanaflynn/stats/clip.go) [coefficient_of_variation.go](/src/github.com/montanaflynn/stats/coefficient_of_variation.go) [correlation.go](/src/github.com/montanaflynn/stats/correlation.go) [cumulative.go](/src/github.com/montanaflynn/stats/cumulative.go) [cumulative_sum.go](/src/github.com/montanaflynn/stats/cumulative_sum.go) [data.go](/src/github.com/montanaflynn/stats/data.go) [describe.go](/src/github.com/montanaflynn/stats/describe.go) [deviation.go](/src/github.com/montanaflynn/stats/deviation.go) [diff.go](/src/github.com/montanaflynn/stats/diff.go) [distances.go](/src/github.com/montanaflynn/stats/distances.go) [doc.go](/src/github.com/montanaflynn/stats/doc.go) [entropy.go](/src/github.com/montanaflynn/stats/entropy.go) [errors.go](/src/github.com/montanaflynn/stats/errors.go) [ewma.go](/src/github.com/montanaflynn/stats/ewma.go) [extremes.go](/src/github.com/montanaflynn/stats/extremes.go) [geometric_distribution.go](/src/github.com/montanaflynn/stats/geometric_distribution.go) [histogram.go](/src/github.com/montanaflynn/stats/histogram.go) [interp.go](/src/github.com/montanaflynn/stats/interp.go) [kendall.go](/src/github.com/montanaflynn/stats/kendall.go) [kurtosis.go](/src/github.com/montanaflynn/stats/kurtosis.go) [legacy.go](/src/github.com/montanaflynn/stats/legacy.go) [load.go](/src/github.com/montanaflynn/stats/load.go) [max.go](/src/github.com/montanaflynn/stats/max.go) [mean.go](/src/github.com/montanaflynn/stats/mean.go) [median.go](/src/github.com/montanaflynn/stats/median.go) [min.go](/src/github.com/montanaflynn/stats/min.go) [mode.go](/src/github.com/montanaflynn/stats/mode.go) [moving.go](/src/github.com/montanaflynn/stats/moving.go) [norm.go](/src/github.com/montanaflynn/stats/norm.go) [outlier.go](/src/github.com/montanaflynn/stats/outlier.go) [percentile.go](/src/github.com/montanaflynn/stats/percentile.go) [percentile_of_score.go](/src/github.com/montanaflynn/stats/percentile_of_score.go) [percentile_weighted.go](/src/github.com/montanaflynn/stats/percentile_weighted.go) [product.go](/src/github.com/montanaflynn/stats/product.go) [quartile.go](/src/github.com/montanaflynn/stats/quartile.go) [rank.go](/src/github.com/montanaflynn/stats/rank.go) [ranksum.go](/src/github.com/montanaflynn/stats/ranksum.go) [regression.go](/src/github.com/montanaflynn/stats/regression.go) [rescale.go](/src/github.com/montanaflynn/stats/rescale.go) [rms.go](/src/github.com/montanaflynn/stats/rms.go) [rolling.go](/src/github.com/montanaflynn/stats/rolling.go) [round.go](/src/github.com/montanaflynn/stats/round.go) [sample.go](/src/github.com/montanaflynn/stats/sample.go) [sem.go](/src/github.com/montanaflynn/stats/sem.go) [sigmoid.go](/src/github.com/montanaflynn/stats/sigmoid.go) [skewness.go](/src/github.com/montanaflynn/stats/skewness.go) [softmax.go](/src/github.com/montanaflynn/stats/softmax.go) [sum.go](/src/github.com/montanaflynn/stats/sum.go) [trimmed_mean.go](/src/github.com/montanaflynn/stats/trimmed_mean.go) [ttest.go](/src/github.com/montanaflynn/stats/ttest.go) [util.go](/src/github.com/montanaflynn/stats/util.go) [variance.go](/src/github.com/montanaflynn/stats/variance.go) [weighted_mean.go](/src/github.com/montanaflynn/stats/weighted_mean.go) [winsorize.go](/src/github.com/montanaflynn/stats/winsorize.go) [zscore.go](/src/github.com/montanaflynn/stats/zscore.go) [ztest.go](/src/github.com/montanaflynn/stats/ztest.go) @@ -223,7 +328,25 @@ Legacy error names that didn't start with Err -## func [AutoCorrelation](/correlation.go?s=853:918#L38) +## func [ArgMax](/extremes.go?s=129:172#L5) +``` go +func ArgMax(input Float64Data) (int, error) +``` +ArgMax finds the index of the highest number in a slice, +returning the first occurrence in the case of ties + + + +## func [ArgMin](/extremes.go?s=671:714#L28) +``` go +func ArgMin(input Float64Data) (int, error) +``` +ArgMin finds the index of the lowest number in a slice, +returning the first occurrence in the case of ties + + + +## func [AutoCorrelation](/correlation.go?s=2282:2347#L102) ``` go func AutoCorrelation(data Float64Data, lags int) (float64, error) ``` @@ -239,7 +362,29 @@ ChebyshevDistance computes the Chebyshev distance between two data sets -## func [Correlation](/correlation.go?s=112:171#L8) +## func [Clip](/clip.go?s=109:174#L5) +``` go +func Clip(input Float64Data, min, max float64) ([]float64, error) +``` +Clip clamps each value in the input slice into the +inclusive range between min and max. + + + +## func [CoefficientOfVariation](/coefficient_of_variation.go?s=322:385#L11) +``` go +func CoefficientOfVariation(input Float64Data) (float64, error) +``` +CoefficientOfVariation finds the coefficient of variation of a slice +of floats, defined as the sample standard deviation divided by the +mean. This matches the behavior of Python's scipy.stats.variation +with ddof=1. + +The input must not be empty and its mean must not be zero. + + + +## func [Correlation](/correlation.go?s=120:179#L9) ``` go func Correlation(data1, data2 Float64Data) (float64, error) ``` @@ -263,6 +408,30 @@ CovariancePopulation computes covariance for entire population between two varia +## func [CumulativeMax](/cumulative.go?s=486:542#L24) +``` go +func CumulativeMax(input Float64Data) ([]float64, error) +``` +CumulativeMax calculates the cumulative maximum of the input slice + + + +## func [CumulativeMin](/cumulative.go?s=874:930#L44) +``` go +func CumulativeMin(input Float64Data) ([]float64, error) +``` +CumulativeMin calculates the cumulative minimum of the input slice + + + +## func [CumulativeProduct](/cumulative.go?s=89:149#L4) +``` go +func CumulativeProduct(input Float64Data) ([]float64, error) +``` +CumulativeProduct calculates the cumulative product of the input slice + + + ## func [CumulativeSum](/cumulative_sum.go?s=81:137#L4) ``` go func CumulativeSum(input Float64Data) ([]float64, error) @@ -271,6 +440,30 @@ CumulativeSum calculates the cumulative sum of the input slice +## func [Diff](/diff.go?s=238:285#L7) +``` go +func Diff(input Float64Data) ([]float64, error) +``` +Diff calculates the successive differences of the input slice, +returning input[i] - input[i-1] for each i in 1..len(input)-1. +The output has length len(input) - 1; a single-element input +returns an empty slice. + + + +## func [EWMA](/ewma.go?s=392:454#L9) +``` go +func EWMA(input Float64Data, alpha float64) ([]float64, error) +``` +EWMA calculates the exponentially weighted moving average of the input +with smoothing factor alpha. The first output equals the first input and +each subsequent entry is alpha*input[i] + (1-alpha)*output[i-1], so the +result has the same length as the input. The alpha must satisfy +0 < alpha <= 1 or ErrBounds is returned. An empty input returns +ErrEmptyInput. + + + ## func [Entropy](/entropy.go?s=77:125#L6) ``` go func Entropy(input Float64Data) (float64, error) @@ -304,7 +497,7 @@ GeometricMean gets the geometric mean for a slice of numbers -## func [HarmonicMean](/mean.go?s=717:770#L40) +## func [HarmonicMean](/mean.go?s=842:895#L41) ``` go func HarmonicMean(input Float64Data) (float64, error) ``` @@ -312,6 +505,18 @@ HarmonicMean gets the harmonic mean for a slice of numbers +## func [Histogram](/histogram.go?s=327:396#L10) +``` go +func Histogram(input Float64Data, bins int) ([]int, []float64, error) +``` +Histogram calculates the histogram of a slice using the given +number of equal-width bins over [min, max], returning the count +of values in each bin along with the bins+1 bin edges. Each bin +is half-open [edges[i], edges[i+1]) except the last, which also +includes the maximum value. + + + ## func [InterQuartileRange](/quartile.go?s=821:880#L45) ``` go func InterQuartileRange(input Float64Data) (float64, error) @@ -320,6 +525,39 @@ InterQuartileRange finds the range between Q1 and Q3 +## func [Interp](/interp.go?s=547:600#L12) +``` go +func Interp(x, xp, fp Float64Data) ([]float64, error) +``` +Interp calculates the one-dimensional piecewise-linear interpolant to a +function with given discrete data points (xp, fp), evaluated at each x. +Values of x below xp[0] return fp[0] and values above xp[len(xp)-1] return +fp[len(xp)-1], so no extrapolation is performed. Unlike numpy's interp, +which silently returns nonsense for unsorted coordinates, xp must be +strictly increasing or ErrBounds is returned. An empty x or xp returns +ErrEmptyInput and xp and fp of different lengths return ErrSize. + + + +## func [KendallTau](/kendall.go?s=302:360#L9) +``` go +func KendallTau(data1, data2 Float64Data) (float64, error) +``` +KendallTau calculates Kendall's tau-b rank correlation coefficient +between two variables. Tau-b corrects for ties, matching the values +produced by SciPy's kendalltau and pandas' corr(method="kendall"). +Pairs are compared with a simple O(n^2) loop for clarity. + + + +## func [Kurtosis](/kurtosis.go?s=97:146#L6) +``` go +func Kurtosis(input Float64Data) (float64, error) +``` +Kurtosis computes the population excess kurtosis of the dataset + + + ## func [ManhattanDistance](/distances.go?s=1277:1365#L50) ``` go func ManhattanDistance(dataPointX, dataPointY Float64Data) (distance float64, err error) @@ -417,7 +655,81 @@ Mode gets the mode [most frequent value(s)] of a slice of float64s -## func [Ncr](/norm.go?s=7384:7406#L239) +## func [MovingAverage](/rolling.go?s=362:430#L8) +``` go +func MovingAverage(input Float64Data, window int) ([]float64, error) +``` +MovingAverage calculates the rolling mean of the input over a trailing +window. Only fully-populated windows produce output, so the result has +len(input)-window+1 entries and entry i is the mean of input[i : i+window]. +The window must satisfy 1 <= window <= len(input) or ErrBounds is +returned. An empty input returns ErrEmptyInput. + + + +## func [MovingMax](/moving.go?s=1892:1956#L60) +``` go +func MovingMax(input Float64Data, window int) ([]float64, error) +``` +MovingMax calculates the rolling maximum of the input over a trailing +window. Only fully-populated windows produce output, so the result has +len(input)-window+1 entries and entry i is the maximum of +input[i : i+window]. The window must satisfy 1 <= window <= len(input) or +ErrBounds is returned. An empty input returns ErrEmptyInput. + + + +## func [MovingMedian](/moving.go?s=365:432#L8) +``` go +func MovingMedian(input Float64Data, window int) ([]float64, error) +``` +MovingMedian calculates the rolling median of the input over a trailing +window. Only fully-populated windows produce output, so the result has +len(input)-window+1 entries and entry i is the median of input[i : i+window]. +The window must satisfy 1 <= window <= len(input) or ErrBounds is +returned. An empty input returns ErrEmptyInput. + + + +## func [MovingMin](/moving.go?s=1136:1200#L34) +``` go +func MovingMin(input Float64Data, window int) ([]float64, error) +``` +MovingMin calculates the rolling minimum of the input over a trailing +window. Only fully-populated windows produce output, so the result has +len(input)-window+1 entries and entry i is the minimum of +input[i : i+window]. The window must satisfy 1 <= window <= len(input) or +ErrBounds is returned. An empty input returns ErrEmptyInput. + + + +## func [MovingStdDev](/rolling.go?s=1239:1306#L36) +``` go +func MovingStdDev(input Float64Data, window int) ([]float64, error) +``` +MovingStdDev calculates the rolling sample standard deviation of the input +over a trailing window. Only fully-populated windows produce output, so the +result has len(input)-window+1 entries and entry i is the sample standard +deviation of input[i : i+window]. The window must satisfy +2 <= window <= len(input) or ErrBounds is returned, since the sample +standard deviation of a single value is undefined. An empty input returns +ErrEmptyInput. + + + +## func [MovingSum](/moving.go?s=2640:2704#L86) +``` go +func MovingSum(input Float64Data, window int) ([]float64, error) +``` +MovingSum calculates the rolling sum of the input over a trailing +window. Only fully-populated windows produce output, so the result has +len(input)-window+1 entries and entry i is the sum of input[i : i+window]. +The window must satisfy 1 <= window <= len(input) or ErrBounds is +returned. An empty input returns ErrEmptyInput. + + + +## func [Ncr](/norm.go?s=7623:7645#L245) ``` go func Ncr(n, r int) int ``` @@ -426,7 +738,7 @@ Aaron Cannon's algorithm. -## func [NormBoxMullerRvs](/norm.go?s=667:736#L23) +## func [NormBoxMullerRvs](/norm.go?s=906:975#L29) ``` go func NormBoxMullerRvs(loc float64, scale float64, size int) []float64 ``` @@ -435,7 +747,7 @@ For more information please visit: func [NormCdf](/norm.go?s=1826:1885#L52) +## func [NormCdf](/norm.go?s=2065:2124#L58) ``` go func NormCdf(x float64, loc float64, scale float64) float64 ``` @@ -443,7 +755,7 @@ NormCdf is the cumulative distribution function. -## func [NormEntropy](/norm.go?s=5773:5825#L180) +## func [NormEntropy](/norm.go?s=6012:6064#L186) ``` go func NormEntropy(loc float64, scale float64) float64 ``` @@ -451,7 +763,7 @@ NormEntropy is the differential entropy of the RV. -## func [NormFit](/norm.go?s=6058:6097#L187) +## func [NormFit](/norm.go?s=6297:6336#L193) ``` go func NormFit(data []float64) [2]float64 ``` @@ -461,7 +773,7 @@ Returns array of Mean followed by Standard Deviation. -## func [NormInterval](/norm.go?s=6976:7047#L221) +## func [NormInterval](/norm.go?s=7215:7286#L227) ``` go func NormInterval(alpha float64, loc float64, scale float64) [2]float64 ``` @@ -469,7 +781,7 @@ NormInterval finds endpoints of the range that contains alpha percent of the dis -## func [NormIsf](/norm.go?s=4330:4393#L137) +## func [NormIsf](/norm.go?s=4569:4632#L143) ``` go func NormIsf(p float64, loc float64, scale float64) (x float64) ``` @@ -477,7 +789,7 @@ NormIsf is the inverse survival function (inverse of sf). -## func [NormLogCdf](/norm.go?s=2016:2078#L57) +## func [NormLogCdf](/norm.go?s=2255:2317#L63) ``` go func NormLogCdf(x float64, loc float64, scale float64) float64 ``` @@ -485,7 +797,7 @@ NormLogCdf is the log of the cumulative distribution function. -## func [NormLogPdf](/norm.go?s=1590:1652#L47) +## func [NormLogPdf](/norm.go?s=1829:1891#L53) ``` go func NormLogPdf(x float64, loc float64, scale float64) float64 ``` @@ -493,7 +805,7 @@ NormLogPdf is the log of the probability density function. -## func [NormLogSf](/norm.go?s=2423:2484#L67) +## func [NormLogSf](/norm.go?s=2662:2723#L73) ``` go func NormLogSf(x float64, loc float64, scale float64) float64 ``` @@ -501,7 +813,7 @@ NormLogSf is the log of the survival function. -## func [NormMean](/norm.go?s=6560:6609#L206) +## func [NormMean](/norm.go?s=6799:6848#L212) ``` go func NormMean(loc float64, scale float64) float64 ``` @@ -509,7 +821,7 @@ NormMean is the mean/expected value of the distribution. -## func [NormMedian](/norm.go?s=6431:6482#L201) +## func [NormMedian](/norm.go?s=6670:6721#L207) ``` go func NormMedian(loc float64, scale float64) float64 ``` @@ -517,7 +829,7 @@ NormMedian is the median of the distribution. -## func [NormMoment](/norm.go?s=4694:4752#L146) +## func [NormMoment](/norm.go?s=4933:4991#L152) ``` go func NormMoment(n int, loc float64, scale float64) float64 ``` @@ -526,7 +838,7 @@ For more information please visit: func [NormPdf](/norm.go?s=1357:1416#L42) +## func [NormPdf](/norm.go?s=1596:1655#L48) ``` go func NormPdf(x float64, loc float64, scale float64) float64 ``` @@ -534,7 +846,7 @@ NormPdf is the probability density function. -## func [NormPpf](/norm.go?s=2854:2917#L75) +## func [NormPpf](/norm.go?s=3093:3156#L81) ``` go func NormPpf(p float64, loc float64, scale float64) (x float64) ``` @@ -545,7 +857,7 @@ For more information please visit: func [NormPpfRvs](/norm.go?s=247:310#L12) +## func [NormPpfRvs](/norm.go?s=486:549#L18) ``` go func NormPpfRvs(loc float64, scale float64, size int) []float64 ``` @@ -554,7 +866,16 @@ For more information please visit: func [NormSf](/norm.go?s=2250:2308#L62) +## func [NormSample](/norm.go?s=194:257#L12) +``` go +func NormSample(loc float64, scale float64, size int) []float64 +``` +NormSample generates random samples from a normal distribution +with the given mean (loc) and standard deviation (scale). + + + +## func [NormSf](/norm.go?s=2489:2547#L68) ``` go func NormSf(x float64, loc float64, scale float64) float64 ``` @@ -562,7 +883,7 @@ NormSf is the survival function (also defined as 1 - cdf, but sf is sometimes mo -## func [NormStats](/norm.go?s=5277:5345#L162) +## func [NormStats](/norm.go?s=5516:5584#L168) ``` go func NormStats(loc float64, scale float64, moments string) []float64 ``` @@ -573,7 +894,7 @@ Returns array of m v s k in that order. -## func [NormStd](/norm.go?s=6814:6862#L216) +## func [NormStd](/norm.go?s=7053:7101#L222) ``` go func NormStd(loc float64, scale float64) float64 ``` @@ -581,7 +902,7 @@ NormStd is the standard deviation of the distribution. -## func [NormVar](/norm.go?s=6675:6723#L211) +## func [NormVar](/norm.go?s=6914:6962#L217) ``` go func NormVar(loc float64, scale float64) float64 ``` @@ -589,7 +910,7 @@ NormVar is the variance of the distribution. -## func [Pearson](/correlation.go?s=655:710#L33) +## func [Pearson](/correlation.go?s=663:718#L34) ``` go func Pearson(data1, data2 Float64Data) (float64, error) ``` @@ -597,6 +918,20 @@ Pearson calculates the Pearson product-moment correlation coefficient between tw +## func [PercentChange](/diff.go?s=891:947#L29) +``` go +func PercentChange(input Float64Data) ([]float64, error) +``` +PercentChange calculates the fractional change between successive +elements of the input slice, returning +(input[i] - input[i-1]) / input[i-1] for each i in 1..len(input)-1. +The output has length len(input) - 1; a single-element input +returns an empty slice. A zero denominator follows IEEE 754 +semantics, yielding +Inf, -Inf, or NaN (for 0/0), matching the +behavior of pandas pct_change. + + + ## func [Percentile](/percentile.go?s=598:681#L20) ``` go func Percentile(input Float64Data, percent float64) (percentile float64, err error) @@ -626,6 +961,56 @@ PercentileNearestRank finds the relative standing in a slice of floats using the +## func [PercentileOfScore](/percentile_of_score.go?s=374:447#L11) +``` go +func PercentileOfScore(input Float64Data, score float64) (float64, error) +``` +PercentileOfScore calculates the percentile rank of a score +relative to a slice of floats, defined as the percentage of +values strictly below the score plus half the percentage of +values equal to the score. The result is between 0 and 100. +This matches the behavior of Python's +scipy.stats.percentileofscore with kind="rank". + + + +## func [PercentileWeighted](/percentile_weighted.go?s=620:719#L19) +``` go +func PercentileWeighted(data, weights Float64Data, percent float64) (percentile float64, err error) +``` +PercentileWeighted finds the weighted percentile of a slice of floats +using the weighted empirical CDF (inverse CDF / nearest-rank method). + +For a given percent p, it returns the smallest data value x such that +the cumulative weight of all values <= x is at least p% of the total +weight. This matches the behavior of Python's statsmodels +DescrStatsW.quantile. + +The data and weights slices must be the same length. Weights must be +non-negative and at least one weight must be positive. The percent +parameter must be between 0 and 100 (exclusive). + + + +## func [PopulationKurtosis](/kurtosis.go?s=391:450#L13) +``` go +func PopulationKurtosis(input Float64Data) (float64, error) +``` +PopulationKurtosis computes the population excess kurtosis (Fisher +definition) using the fourth central moment normalized by the squared +variance, so a normal distribution has a kurtosis of zero. + + + +## func [PopulationSkewness](/skewness.go?s=318:377#L12) +``` go +func PopulationSkewness(input Float64Data) (float64, error) +``` +PopulationSkewness computes the population skewness using the third +central moment normalized by the cube of the standard deviation. + + + ## func [PopulationVariance](/variance.go?s=828:896#L31) ``` go func PopulationVariance(input Float64Data) (pvar float64, err error) @@ -644,6 +1029,56 @@ See https://en.wi +## func [Product](/product.go?s=299:347#L10) +``` go +func Product(input Float64Data) (float64, error) +``` +Product calculates the product of a slice of floats by +multiplying the values from left to right. It is the scalar +counterpart of CumulativeProduct. Large inputs can overflow +to Inf; use GeometricMean for an overflow-safe summary of +multiplicative data. + + + +## func [RMS](/rms.go?s=156:200#L7) +``` go +func RMS(input Float64Data) (float64, error) +``` +RMS calculates the root mean square of a slice of floats, +defined as the square root of the mean of the squared values. + + + +## func [Range](/extremes.go?s=1181:1227#L51) +``` go +func Range(input Float64Data) (float64, error) +``` +Range finds the difference between the highest and +lowest numbers in a slice + + + +## func [Rank](/rank.go?s=183:230#L6) +``` go +func Rank(input Float64Data) ([]float64, error) +``` +Rank assigns fractional (average) ranks to the input values. +Ranks are 1-based and tied values receive the average of the +ranks they would have been assigned. + + + +## func [Rescale](/rescale.go?s=174:224#L6) +``` go +func Rescale(input Float64Data) ([]float64, error) +``` +Rescale normalizes the input values to the range of 0 to 1 +by subtracting the minimum and dividing by the range, +also known as min-max normalization. + + + ## func [Round](/round.go?s=88:154#L6) ``` go func Round(input float64, places int) (rounded float64, err error) @@ -652,6 +1087,17 @@ Round a float to a specific decimal place or precision +## func [SEM](/sem.go?s=265:309#L9) +``` go +func SEM(input Float64Data) (float64, error) +``` +SEM calculates the standard error of the mean of a slice +of floats, defined as the sample standard deviation divided +by the square root of the sample size. This matches the +behavior of Python's scipy.stats.sem with ddof=1. + + + ## func [Sample](/sample.go?s=112:192#L9) ``` go func Sample(input Float64Data, takenum int, replacement bool) ([]float64, error) @@ -660,6 +1106,24 @@ Sample returns sample from input with replacement or without +## func [SampleKurtosis](/kurtosis.go?s=1071:1126#L41) +``` go +func SampleKurtosis(input Float64Data) (float64, error) +``` +SampleKurtosis computes the bias-corrected sample excess kurtosis, +matching pandas .kurt() and scipy.stats.kurtosis with bias=False. + + + +## func [SampleSkewness](/skewness.go?s=1049:1104#L44) +``` go +func SampleSkewness(input Float64Data) (float64, error) +``` +SampleSkewness computes the adjusted Fisher-Pearson standardized moment +coefficient, correcting for bias in small samples. + + + ## func [SampleVariance](/variance.go?s=1058:1122#L42) ``` go func SampleVariance(input Float64Data) (svar float64, err error) @@ -679,6 +1143,14 @@ activation function. +## func [Skewness](/skewness.go?s=90:139#L6) +``` go +func Skewness(input Float64Data) (float64, error) +``` +Skewness computes the population skewness of the dataset + + + ## func [SoftMax](/softmax.go?s=206:256#L8) ``` go func SoftMax(input Float64Data) ([]float64, error) @@ -689,6 +1161,16 @@ is commonly used in machine learning neural networks. +## func [Spearman](/correlation.go?s=1006:1062#L41) +``` go +func Spearman(data1, data2 Float64Data) (float64, error) +``` +Spearman calculates the Spearman rank correlation coefficient between two variables. +It works by ranking the data and then computing the Pearson correlation of the ranks. +This method handles tied values using fractional (average) ranking. + + + ## func [StableSample](/sample.go?s=974:1042#L50) ``` go func StableSample(input Float64Data, takenum int) ([]float64, error) @@ -745,6 +1227,24 @@ Sum adds all the numbers of a slice together +## func [TTest](/ttest.go?s=505:604#L16) +``` go +func TTest(data1, data2 Float64Data, populationMean float64) (t float64, pvalue float64, err error) +``` +TTest performs a one-sample or two-sample (independent) Student's t-test. + +For a one-sample t-test, pass the sample data as data1, nil for data2, +and the expected population mean as populationMean. + +For a two-sample independent t-test (assuming equal variance), pass both +sample datasets. The populationMean parameter is ignored in this case. + +Returns the t statistic and the two-tailed p-value. + +https://en.wikipedia.org/wiki/Student%27s_t-test + + + ## func [Trimean](/quartile.go?s=1320:1368#L65) ``` go func Trimean(input Float64Data) (float64, error) @@ -753,6 +1253,21 @@ Trimean finds the average of the median and the midhinge +## func [TrimmedMean](/trimmed_mean.go?s=450:519#L13) +``` go +func TrimmedMean(input Float64Data, percent float64) (float64, error) +``` +TrimmedMean finds the mean of a slice of floats after removing a +fraction of the smallest and largest values. This matches the +behavior of Python's scipy.stats.trim_mean. + +The percent parameter is the fraction removed from each tail and +must be in the range [0, 0.5). The number of elements trimmed from +each tail is floor(len(input) * percent). A percent of zero returns +the same result as Mean. + + + ## func [VarGeom](/geometric_distribution.go?s=885:933#L37) ``` go func VarGeom(p float64) (exp float64, err error) @@ -786,6 +1301,67 @@ Variance the amount of variation in the dataset +## func [WeightedMean](/weighted_mean.go?s=415:476#L12) +``` go +func WeightedMean(data, weights Float64Data) (float64, error) +``` +WeightedMean finds the weighted mean of a slice of floats, defined as +the sum of each data value multiplied by its weight divided by the sum +of all the weights. This matches the behavior of Python's +numpy.average with the weights argument. + +The data and weights slices must be the same length. Weights must be +non-negative and at least one weight must be positive. + + + +## func [Winsorize](/winsorize.go?s=618:687#L16) +``` go +func Winsorize(input Float64Data, percent float64) ([]float64, error) +``` +Winsorize limits the effect of outliers in a slice of floats by +clamping a fraction of the smallest and largest values. This matches +the behavior of Python's scipy.stats.mstats.winsorize with symmetric +limits. + +The percent parameter is the fraction clamped in each tail and must +be in the range [0, 0.5). With k = floor(len(input) * percent), +values below the k-th smallest value are set to it and values above +the k-th largest value are set to it. The returned slice preserves +the original element order and a percent of zero returns a copy of +the input. + + + +## func [ZScore](/zscore.go?s=205:254#L6) +``` go +func ZScore(input Float64Data) ([]float64, error) +``` +ZScore standardizes the input values by subtracting the mean +and dividing by the sample standard deviation, returning the +number of standard deviations each value is from the mean. + + + +## func [ZTest](/ztest.go?s=537:654#L17) +``` go +func ZTest(data1, data2 Float64Data, populationMean, populationStdDev float64) (z float64, pvalue float64, err error) +``` +ZTest performs a one-sample or two-sample Z-test. + +For a one-sample Z-test, pass the sample data as data1, nil for data2, +the known population mean as populationMean, and the known population +standard deviation as populationStdDev. + +For a two-sample Z-test, pass both sample datasets and the known population +standard deviations. The populationMean parameter is ignored in this case. + +Returns the Z statistic and the two-tailed p-value. + +https://en.wikipedia.org/wiki/Z-test + + + ## type [Coordinate](/regression.go?s=143:183#L9) ``` go @@ -826,7 +1402,7 @@ LogReg is a shortcut to LogarithmicRegression -## type [Description](/describe.go?s=89:349#L6) +## type [Description](/describe.go?s=89:381#L6) ``` go type Description struct { Count int @@ -834,6 +1410,7 @@ type Description struct { Std float64 Max float64 Min float64 + Range float64 DescriptionPercentiles []descriptionPercentile AllowedNaN bool } @@ -847,14 +1424,14 @@ Holds information about the dataset provided to Describe -### func [Describe](/describe.go?s=579:672#L23) +### func [Describe](/describe.go?s=611:704#L24) ``` go func Describe(input Float64Data, allowNaN bool, percentiles *[]float64) (*Description, error) ``` Describe generates descriptive statistics about a provided dataset, similar to python's pandas.describe() -### func [DescribePercentileFunc](/describe.go?s=917:1084#L29) +### func [DescribePercentileFunc](/describe.go?s=949:1116#L30) ``` go func DescribePercentileFunc(input Float64Data, allowNaN bool, percentiles *[]float64, percentileFunc func(Float64Data, float64) (float64, error)) (*Description, error) ``` @@ -865,7 +1442,7 @@ Takes in a function to use for percentile calculation -### func (\*Description) [String](/describe.go?s=2078:2127#L68) +### func (\*Description) [String](/describe.go?s=2161:2210#L71) ``` go func (d *Description) String(decimals int) string ``` @@ -877,6 +1454,7 @@ Represents the Description instance in a string format with specified number of std 0.82 max 3.00 min 1.00 + range 2.00 25.00% NaN 50.00% 1.50 75.00% 2.50 @@ -907,7 +1485,25 @@ LoadRawData parses and converts a slice of mixed data types to floats -### func (Float64Data) [AutoCorrelation](/data.go?s=3257:3320#L91) +### func (Float64Data) [ArgMax](/extremes.go?s=1521:1563#L66) +``` go +func (f Float64Data) ArgMax() (int, error) +``` +ArgMax returns the index of the highest number in the data + + + + +### func (Float64Data) [ArgMin](/extremes.go?s=1647:1689#L69) +``` go +func (f Float64Data) ArgMin() (int, error) +``` +ArgMin returns the index of the lowest number in the data + + + + +### func (Float64Data) [AutoCorrelation](/data.go?s=3274:3337#L91) ``` go func (f Float64Data) AutoCorrelation(lags int) (float64, error) ``` @@ -916,7 +1512,26 @@ AutoCorrelation is the correlation of a signal with a delayed copy of itself as -### func (Float64Data) [Correlation](/data.go?s=3058:3122#L86) +### func (Float64Data) [Clip](/clip.go?s=550:612#L30) +``` go +func (f Float64Data) Clip(min, max float64) ([]float64, error) +``` +Clip clamps each value in the input slice into the +inclusive range between min and max. + + + + +### func (Float64Data) [CoefficientOfVariation](/coefficient_of_variation.go?s=768:830#L29) +``` go +func (f Float64Data) CoefficientOfVariation() (float64, error) +``` +CoefficientOfVariation finds the sample standard deviation divided by the mean + + + + +### func (Float64Data) [Correlation](/data.go?s=3075:3139#L86) ``` go func (f Float64Data) Correlation(d Float64Data) (float64, error) ``` @@ -925,7 +1540,7 @@ Correlation describes the degree of relationship between two sets of data -### func (Float64Data) [Covariance](/data.go?s=4801:4864#L141) +### func (Float64Data) [Covariance](/data.go?s=4996:5059#L146) ``` go func (f Float64Data) Covariance(d Float64Data) (float64, error) ``` @@ -934,7 +1549,7 @@ Covariance is a measure of how much two sets of data change -### func (Float64Data) [CovariancePopulation](/data.go?s=4983:5056#L146) +### func (Float64Data) [CovariancePopulation](/data.go?s=5178:5251#L151) ``` go func (f Float64Data) CovariancePopulation(d Float64Data) (float64, error) ``` @@ -943,6 +1558,33 @@ CovariancePopulation computes covariance for entire population between two varia +### func (Float64Data) [CumulativeMax](/cumulative.go?s=1416:1471#L69) +``` go +func (f Float64Data) CumulativeMax() ([]float64, error) +``` +CumulativeMax calculates the cumulative maximum of the data + + + + +### func (Float64Data) [CumulativeMin](/cumulative.go?s=1565:1620#L74) +``` go +func (f Float64Data) CumulativeMin() ([]float64, error) +``` +CumulativeMin calculates the cumulative minimum of the data + + + + +### func (Float64Data) [CumulativeProduct](/cumulative.go?s=1259:1318#L64) +``` go +func (f Float64Data) CumulativeProduct() ([]float64, error) +``` +CumulativeProduct calculates the cumulative product of the data + + + + ### func (Float64Data) [CumulativeSum](/data.go?s=883:938#L28) ``` go func (f Float64Data) CumulativeSum() ([]float64, error) @@ -952,7 +1594,25 @@ CumulativeSum returns the cumulative sum of the data -### func (Float64Data) [Entropy](/data.go?s=5480:5527#L162) +### func (Float64Data) [Diff](/diff.go?s=1220:1266#L45) +``` go +func (f Float64Data) Diff() ([]float64, error) +``` +Diff returns the successive differences of the data + + + + +### func (Float64Data) [EWMA](/ewma.go?s=848:907#L30) +``` go +func (f Float64Data) EWMA(alpha float64) ([]float64, error) +``` +EWMA returns the exponentially weighted moving average of the data with smoothing factor alpha + + + + +### func (Float64Data) [Entropy](/data.go?s=5675:5722#L167) ``` go func (f Float64Data) Entropy() (float64, error) ``` @@ -961,11 +1621,11 @@ Entropy provides calculation of the entropy -### func (Float64Data) [GeometricMean](/data.go?s=1332:1385#L40) +### func (Float64Data) [GeometricMean](/data.go?s=1340:1393#L40) ``` go func (f Float64Data) GeometricMean() (float64, error) ``` -GeometricMean returns the median of the data +GeometricMean returns the geometric mean of the data @@ -979,16 +1639,25 @@ Get item in slice -### func (Float64Data) [HarmonicMean](/data.go?s=1460:1512#L43) +### func (Float64Data) [HarmonicMean](/data.go?s=1477:1529#L43) ``` go func (f Float64Data) HarmonicMean() (float64, error) ``` -HarmonicMean returns the mode of the data +HarmonicMean returns the harmonic mean of the data + + + + +### func (Float64Data) [Histogram](/histogram.go?s=1359:1425#L55) +``` go +func (f Float64Data) Histogram(bins int) ([]int, []float64, error) +``` +Histogram returns the counts and equal-width bin edges of the data -### func (Float64Data) [InterQuartileRange](/data.go?s=3755:3813#L106) +### func (Float64Data) [InterQuartileRange](/data.go?s=3950:4008#L111) ``` go func (f Float64Data) InterQuartileRange() (float64, error) ``` @@ -997,6 +1666,25 @@ InterQuartileRange finds the range between Q1 and Q3 +### func (Float64Data) [KendallTau](/kendall.go?s=1384:1447#L55) +``` go +func (f Float64Data) KendallTau(d Float64Data) (float64, error) +``` +KendallTau calculates Kendall's tau-b rank correlation coefficient +between two variables. + + + + +### func (Float64Data) [Kurtosis](/kurtosis.go?s=1501:1549#L58) +``` go +func (f Float64Data) Kurtosis() (float64, error) +``` +Kurtosis finds the population excess kurtosis of a slice of floats + + + + ### func (Float64Data) [Len](/data.go?s=217:247#L10) ``` go func (f Float64Data) Len() int @@ -1042,7 +1730,7 @@ Median returns the median of the data -### func (Float64Data) [MedianAbsoluteDeviation](/data.go?s=1630:1693#L46) +### func (Float64Data) [MedianAbsoluteDeviation](/data.go?s=1647:1710#L46) ``` go func (f Float64Data) MedianAbsoluteDeviation() (float64, error) ``` @@ -1051,7 +1739,7 @@ MedianAbsoluteDeviation the median of the absolute deviations from the dataset m -### func (Float64Data) [MedianAbsoluteDeviationPopulation](/data.go?s=1842:1915#L51) +### func (Float64Data) [MedianAbsoluteDeviationPopulation](/data.go?s=1859:1932#L51) ``` go func (f Float64Data) MedianAbsoluteDeviationPopulation() (float64, error) ``` @@ -1060,7 +1748,7 @@ MedianAbsoluteDeviationPopulation finds the median of the absolute deviations fr -### func (Float64Data) [Midhinge](/data.go?s=3912:3973#L111) +### func (Float64Data) [Midhinge](/data.go?s=4107:4168#L116) ``` go func (f Float64Data) Midhinge(d Float64Data) (float64, error) ``` @@ -1087,7 +1775,61 @@ Mode returns the mode of the data -### func (Float64Data) [Pearson](/data.go?s=3455:3515#L96) +### func (Float64Data) [MovingAverage](/rolling.go?s=1768:1833#L58) +``` go +func (f Float64Data) MovingAverage(window int) ([]float64, error) +``` +MovingAverage returns the rolling mean of the data over a trailing window + + + + +### func (Float64Data) [MovingMax](/moving.go?s=3475:3536#L118) +``` go +func (f Float64Data) MovingMax(window int) ([]float64, error) +``` +MovingMax returns the rolling maximum of the data over a trailing window + + + + +### func (Float64Data) [MovingMedian](/moving.go?s=3125:3189#L108) +``` go +func (f Float64Data) MovingMedian(window int) ([]float64, error) +``` +MovingMedian returns the rolling median of the data over a trailing window + + + + +### func (Float64Data) [MovingMin](/moving.go?s=3303:3364#L113) +``` go +func (f Float64Data) MovingMin(window int) ([]float64, error) +``` +MovingMin returns the rolling minimum of the data over a trailing window + + + + +### func (Float64Data) [MovingStdDev](/rolling.go?s=1969:2033#L63) +``` go +func (f Float64Data) MovingStdDev(window int) ([]float64, error) +``` +MovingStdDev returns the rolling sample standard deviation of the data over a trailing window + + + + +### func (Float64Data) [MovingSum](/moving.go?s=3643:3704#L123) +``` go +func (f Float64Data) MovingSum(window int) ([]float64, error) +``` +MovingSum returns the rolling sum of the data over a trailing window + + + + +### func (Float64Data) [Pearson](/data.go?s=3472:3532#L96) ``` go func (f Float64Data) Pearson(d Float64Data) (float64, error) ``` @@ -1096,7 +1838,16 @@ Pearson calculates the Pearson product-moment correlation coefficient between tw -### func (Float64Data) [Percentile](/data.go?s=2696:2755#L76) +### func (Float64Data) [PercentChange](/diff.go?s=1374:1429#L48) +``` go +func (f Float64Data) PercentChange() ([]float64, error) +``` +PercentChange returns the fractional change between successive elements of the data + + + + +### func (Float64Data) [Percentile](/data.go?s=2713:2772#L76) ``` go func (f Float64Data) Percentile(p float64) (float64, error) ``` @@ -1105,7 +1856,7 @@ Percentile finds the relative standing in a slice of floats -### func (Float64Data) [PercentileNearestRank](/data.go?s=2869:2939#L81) +### func (Float64Data) [PercentileNearestRank](/data.go?s=2886:2956#L81) ``` go func (f Float64Data) PercentileNearestRank(p float64) (float64, error) ``` @@ -1114,7 +1865,25 @@ PercentileNearestRank finds the relative standing using the Nearest Rank method -### func (Float64Data) [PopulationVariance](/data.go?s=4495:4553#L131) +### func (Float64Data) [PercentileOfScore](/percentile_of_score.go?s=786:856#L29) +``` go +func (f Float64Data) PercentileOfScore(score float64) (float64, error) +``` +PercentileOfScore calculates the percentile rank of a score relative to the data + + + + +### func (Float64Data) [PopulationKurtosis](/kurtosis.go?s=1655:1713#L63) +``` go +func (f Float64Data) PopulationKurtosis() (float64, error) +``` +PopulationKurtosis finds the population excess kurtosis of a slice of floats + + + + +### func (Float64Data) [PopulationVariance](/data.go?s=4690:4748#L136) ``` go func (f Float64Data) PopulationVariance() (float64, error) ``` @@ -1123,7 +1892,16 @@ PopulationVariance finds the amount of variance within a population -### func (Float64Data) [Quartile](/data.go?s=3610:3673#L101) +### func (Float64Data) [Product](/product.go?s=544:591#L24) +``` go +func (f Float64Data) Product() (float64, error) +``` +Product calculates the product of the data + + + + +### func (Float64Data) [Quartile](/data.go?s=3805:3868#L106) ``` go func (f Float64Data) Quartile(d Float64Data) (Quartiles, error) ``` @@ -1132,7 +1910,7 @@ Quartile returns the three quartile points from a slice of data -### func (Float64Data) [QuartileOutliers](/data.go?s=2542:2599#L71) +### func (Float64Data) [QuartileOutliers](/data.go?s=2559:2616#L71) ``` go func (f Float64Data) QuartileOutliers() (Outliers, error) ``` @@ -1141,7 +1919,7 @@ QuartileOutliers finds the mild and extreme outliers -### func (Float64Data) [Quartiles](/data.go?s=5628:5679#L167) +### func (Float64Data) [Quartiles](/data.go?s=5823:5874#L172) ``` go func (f Float64Data) Quartiles() (Quartiles, error) ``` @@ -1150,7 +1928,53 @@ Quartiles returns the three quartile points from instance of Float64Data -### func (Float64Data) [Sample](/data.go?s=4208:4269#L121) +### func (Float64Data) [RMS](/rms.go?s=454:497#L21) +``` go +func (f Float64Data) RMS() (float64, error) +``` +RMS calculates the root mean square of the data + + + + +### func (Float64Data) [Range](/extremes.go?s=1795:1840#L72) +``` go +func (f Float64Data) Range() (float64, error) +``` +Range returns the difference between the highest and lowest numbers in the data + + + + +### func (Float64Data) [Rank](/rank.go?s=382:428#L14) +``` go +func (f Float64Data) Rank() ([]float64, error) +``` +Rank assigns fractional (average) ranks to the input values + + + + +### func (Float64Data) [Rescale](/rescale.go?s=603:652#L27) +``` go +func (f Float64Data) Rescale() ([]float64, error) +``` +Rescale normalizes the input values to the range of 0 to 1 +by subtracting the minimum and dividing by the range + + + + +### func (Float64Data) [SEM](/sem.go?s=625:668#L22) +``` go +func (f Float64Data) SEM() (float64, error) +``` +SEM calculates the standard error of the mean of the data + + + + +### func (Float64Data) [Sample](/data.go?s=4403:4464#L126) ``` go func (f Float64Data) Sample(n int, r bool) ([]float64, error) ``` @@ -1159,7 +1983,16 @@ Sample returns sample from input with replacement or without -### func (Float64Data) [SampleVariance](/data.go?s=4652:4706#L136) +### func (Float64Data) [SampleKurtosis](/kurtosis.go?s=1836:1890#L68) +``` go +func (f Float64Data) SampleKurtosis() (float64, error) +``` +SampleKurtosis finds the bias-corrected sample excess kurtosis of a slice of floats + + + + +### func (Float64Data) [SampleVariance](/data.go?s=4847:4901#L141) ``` go func (f Float64Data) SampleVariance() (float64, error) ``` @@ -1168,7 +2001,7 @@ SampleVariance finds the amount of variance within a sample -### func (Float64Data) [Sigmoid](/data.go?s=5169:5218#L151) +### func (Float64Data) [Sigmoid](/data.go?s=5364:5413#L156) ``` go func (f Float64Data) Sigmoid() ([]float64, error) ``` @@ -1177,7 +2010,7 @@ Sigmoid returns the input values along the sigmoid or s-shaped curve -### func (Float64Data) [SoftMax](/data.go?s=5359:5408#L157) +### func (Float64Data) [SoftMax](/data.go?s=5554:5603#L162) ``` go func (f Float64Data) SoftMax() ([]float64, error) ``` @@ -1187,7 +2020,16 @@ with sum of all the probabilities being equal to one. -### func (Float64Data) [StandardDeviation](/data.go?s=2026:2083#L56) +### func (Float64Data) [Spearman](/data.go?s=3648:3709#L101) +``` go +func (f Float64Data) Spearman(d Float64Data) (float64, error) +``` +Spearman calculates the Spearman rank correlation coefficient between two variables. + + + + +### func (Float64Data) [StandardDeviation](/data.go?s=2043:2100#L56) ``` go func (f Float64Data) StandardDeviation() (float64, error) ``` @@ -1196,7 +2038,7 @@ StandardDeviation the amount of variation in the dataset -### func (Float64Data) [StandardDeviationPopulation](/data.go?s=2199:2266#L61) +### func (Float64Data) [StandardDeviationPopulation](/data.go?s=2216:2283#L61) ``` go func (f Float64Data) StandardDeviationPopulation() (float64, error) ``` @@ -1205,7 +2047,7 @@ StandardDeviationPopulation finds the amount of variation from the population -### func (Float64Data) [StandardDeviationSample](/data.go?s=2382:2445#L66) +### func (Float64Data) [StandardDeviationSample](/data.go?s=2399:2462#L66) ``` go func (f Float64Data) StandardDeviationSample() (float64, error) ``` @@ -1232,7 +2074,7 @@ Swap switches out two numbers in slice -### func (Float64Data) [Trimean](/data.go?s=4059:4119#L116) +### func (Float64Data) [Trimean](/data.go?s=4254:4314#L121) ``` go func (f Float64Data) Trimean(d Float64Data) (float64, error) ``` @@ -1241,7 +2083,17 @@ Trimean finds the average of the median and the midhinge -### func (Float64Data) [Variance](/data.go?s=4350:4398#L126) +### func (Float64Data) [TrimmedMean](/trimmed_mean.go?s=1132:1198#L36) +``` go +func (f Float64Data) TrimmedMean(percent float64) (float64, error) +``` +TrimmedMean finds the mean of the data after removing a fraction of +the smallest and largest values from each tail + + + + +### func (Float64Data) [Variance](/data.go?s=4545:4593#L131) ``` go func (f Float64Data) Variance() (float64, error) ``` @@ -1250,6 +2102,35 @@ Variance the amount of variation in the dataset +### func (Float64Data) [WeightedMean](/weighted_mean.go?s=976:1047#L40) +``` go +func (f Float64Data) WeightedMean(weights Float64Data) (float64, error) +``` +WeightedMean finds the weighted mean of the data using the given weights + + + + +### func (Float64Data) [Winsorize](/winsorize.go?s=1319:1385#L48) +``` go +func (f Float64Data) Winsorize(percent float64) ([]float64, error) +``` +Winsorize returns a copy of the data with a fraction of the smallest +and largest values in each tail clamped + + + + +### func (Float64Data) [ZScore](/zscore.go?s=632:680#L27) +``` go +func (f Float64Data) ZScore() ([]float64, error) +``` +ZScore standardizes the input values by subtracting the mean +and dividing by the sample standard deviation + + + + ## type [Outliers](/outlier.go?s=73:139#L4) ``` go type Outliers struct { @@ -1315,7 +2196,7 @@ Series is a container for a series of data -### func [ExponentialRegression](/regression.go?s=1089:1157#L50) +### func [ExponentialRegression](/regression.go?s=1061:1129#L49) ``` go func ExponentialRegression(s Series) (regressions Series, err error) ``` @@ -1329,7 +2210,7 @@ func LinearRegression(s Series) (regressions Series, err error) LinearRegression finds the least squares linear regression on data series -### func [LogarithmicRegression](/regression.go?s=1903:1971#L85) +### func [LogarithmicRegression](/regression.go?s=1875:1943#L84) ``` go func LogarithmicRegression(s Series) (regressions Series, err error) ``` diff --git a/vendor/github.com/montanaflynn/stats/Makefile b/vendor/github.com/montanaflynn/stats/Makefile index 969df12..dfa95a6 100644 --- a/vendor/github.com/montanaflynn/stats/Makefile +++ b/vendor/github.com/montanaflynn/stats/Makefile @@ -24,11 +24,10 @@ docs: godoc2md github.com/montanaflynn/stats | sed -e s#src/target/##g > DOCUMENTATION.md release: - git-chglog --output CHANGELOG.md --next-tag ${TAG} + @test -n "${TAG}" || { echo "TAG is required, e.g. make release TAG=v0.10.0"; exit 1; } + sh scripts/update-changelog.sh ${TAG} git add CHANGELOG.md - git commit -m "Update changelog with ${TAG} changes" - git tag ${TAG} - git-chglog $(TAG) | tail -n +4 | gsed '1s/^/$(TAG)\n/gm' > release-notes.txt + git commit -m "chore: update changelog for ${TAG}" + git tag -a ${TAG} -m "${TAG}" git push origin master ${TAG} - hub release create --copy -F release-notes.txt ${TAG} diff --git a/vendor/github.com/montanaflynn/stats/README.md b/vendor/github.com/montanaflynn/stats/README.md index 1cd4895..c91d25f 100644 --- a/vendor/github.com/montanaflynn/stats/README.md +++ b/vendor/github.com/montanaflynn/stats/README.md @@ -1,6 +1,6 @@ # Stats - Golang Statistics Package -[![][action-svg]][action-url] [![][codecov-svg]][codecov-url] [![][goreport-svg]][goreport-url] [![][godoc-svg]][godoc-url] [![][pkggodev-svg]][pkggodev-url] [![][license-svg]][license-url] +[![][action-svg]][action-url] [![][codecov-svg]][codecov-url] [![][godoc-svg]][godoc-url] [![][pkggodev-svg]][pkggodev-url] [![][license-svg]][license-url] A well tested and comprehensive Golang statistics library / package / module with no dependencies. @@ -14,7 +14,7 @@ go get github.com/montanaflynn/stats ## Example Usage -All the functions can be seen in [examples/main.go](examples/main.go) but here's a little taste: +All the functions can be seen in [examples/functions/main.go](examples/functions/main.go) but here's a little taste: ```go // start with some source data to use @@ -70,19 +70,32 @@ type Float64Data []float64 func LoadRawData(raw interface{}) (f Float64Data) {} +func ArgMax(input Float64Data) (int, error) {} +func ArgMin(input Float64Data) (int, error) {} func AutoCorrelation(data Float64Data, lags int) (float64, error) {} func ChebyshevDistance(dataPointX, dataPointY Float64Data) (distance float64, err error) {} +func Clip(input Float64Data, min, max float64) ([]float64, error) {} +func CoefficientOfVariation(input Float64Data) (float64, error) {} func Correlation(data1, data2 Float64Data) (float64, error) {} func Covariance(data1, data2 Float64Data) (float64, error) {} func CovariancePopulation(data1, data2 Float64Data) (float64, error) {} +func CumulativeMax(input Float64Data) ([]float64, error) {} +func CumulativeMin(input Float64Data) ([]float64, error) {} +func CumulativeProduct(input Float64Data) ([]float64, error) {} func CumulativeSum(input Float64Data) ([]float64, error) {} func Describe(input Float64Data, allowNaN bool, percentiles *[]float64) (*Description, error) {} func DescribePercentileFunc(input Float64Data, allowNaN bool, percentiles *[]float64, percentileFunc func(Float64Data, float64) (float64, error)) (*Description, error) {} +func Diff(input Float64Data) ([]float64, error) {} +func EWMA(input Float64Data, alpha float64) ([]float64, error) {} func Entropy(input Float64Data) (float64, error) {} func EuclideanDistance(dataPointX, dataPointY Float64Data) (distance float64, err error) {} func GeometricMean(input Float64Data) (float64, error) {} func HarmonicMean(input Float64Data) (float64, error) {} +func Histogram(input Float64Data, bins int) ([]int, []float64, error) {} func InterQuartileRange(input Float64Data) (float64, error) {} +func Interp(x, xp, fp Float64Data) ([]float64, error) {} +func KendallTau(data1, data2 Float64Data) (float64, error) {} +func Kurtosis(input Float64Data) (float64, error) {} func ManhattanDistance(dataPointX, dataPointY Float64Data) (distance float64, err error) {} func Max(input Float64Data) (max float64, err error) {} func Mean(input Float64Data) (float64, error) {} @@ -93,6 +106,12 @@ func Midhinge(input Float64Data) (float64, error) {} func Min(input Float64Data) (min float64, err error) {} func MinkowskiDistance(dataPointX, dataPointY Float64Data, lambda float64) (distance float64, err error) {} func Mode(input Float64Data) (mode []float64, err error) {} +func MovingAverage(input Float64Data, window int) ([]float64, error) {} +func MovingMax(input Float64Data, window int) ([]float64, error) {} +func MovingMedian(input Float64Data, window int) ([]float64, error) {} +func MovingMin(input Float64Data, window int) ([]float64, error) {} +func MovingStdDev(input Float64Data, window int) ([]float64, error) {} +func MovingSum(input Float64Data, window int) ([]float64, error) {} func NormBoxMullerRvs(loc float64, scale float64, size int) []float64 {} func NormCdf(x float64, loc float64, scale float64) float64 {} func NormEntropy(loc float64, scale float64) float64 {} @@ -107,20 +126,33 @@ func NormMedian(loc float64, scale float64) float64 {} func NormMoment(n int, loc float64, scale float64) float64 {} func NormPdf(x float64, loc float64, scale float64) float64 {} func NormPpf(p float64, loc float64, scale float64) (x float64) {} +func NormSample(loc float64, scale float64, size int) []float64 {} func NormPpfRvs(loc float64, scale float64, size int) []float64 {} func NormSf(x float64, loc float64, scale float64) float64 {} func NormStats(loc float64, scale float64, moments string) []float64 {} func NormStd(loc float64, scale float64) float64 {} func NormVar(loc float64, scale float64) float64 {} func Pearson(data1, data2 Float64Data) (float64, error) {} +func PercentChange(input Float64Data) ([]float64, error) {} func Percentile(input Float64Data, percent float64) (percentile float64, err error) {} func PercentileNearestRank(input Float64Data, percent float64) (percentile float64, err error) {} +func PercentileOfScore(input Float64Data, score float64) (float64, error) {} +func PercentileWeighted(data, weights Float64Data, percent float64) (percentile float64, err error) {} +func PopulationKurtosis(input Float64Data) (float64, error) {} func PopulationSkewness(input Float64Data) (float64, error) {} func PopulationVariance(input Float64Data) (pvar float64, err error) {} +func Product(input Float64Data) (float64, error) {} +func RMS(input Float64Data) (float64, error) {} +func Range(input Float64Data) (float64, error) {} +func Rank(input Float64Data) ([]float64, error) {} +func Rescale(input Float64Data) ([]float64, error) {} +func SEM(input Float64Data) (float64, error) {} func Sample(input Float64Data, takenum int, replacement bool) ([]float64, error) {} +func SampleKurtosis(input Float64Data) (float64, error) {} func SampleSkewness(input Float64Data) (float64, error) {} func SampleVariance(input Float64Data) (svar float64, err error) {} func Skewness(input Float64Data) (float64, error) {} +func Spearman(data1, data2 Float64Data) (float64, error) {} func Sigmoid(input Float64Data) ([]float64, error) {} func SoftMax(input Float64Data) ([]float64, error) {} func StableSample(input Float64Data, takenum int) ([]float64, error) {} @@ -130,10 +162,16 @@ func StandardDeviationSample(input Float64Data) (sdev float64, err error) {} func StdDevP(input Float64Data) (sdev float64, err error) {} func StdDevS(input Float64Data) (sdev float64, err error) {} func Sum(input Float64Data) (sum float64, err error) {} +func TTest(data1, data2 Float64Data, populationMean float64) (t float64, pvalue float64, err error) {} func Trimean(input Float64Data) (float64, error) {} +func TrimmedMean(input Float64Data, percent float64) (float64, error) {} func VarP(input Float64Data) (sdev float64, err error) {} func VarS(input Float64Data) (sdev float64, err error) {} func Variance(input Float64Data) (sdev float64, err error) {} +func WeightedMean(data, weights Float64Data) (float64, error) {} +func Winsorize(input Float64Data, percent float64) ([]float64, error) {} +func ZScore(input Float64Data) ([]float64, error) {} +func ZTest(data1, data2 Float64Data, populationMean, populationStdDev float64) (z float64, pvalue float64, err error) {} func ProbGeom(a int, b int, p float64) (prob float64, err error) {} func ExpGeom(p float64) (exp float64, err error) {} func VarGeom(p float64) (exp float64, err error) {} @@ -178,7 +216,7 @@ Pull request are always welcome no matter how big or small. I've included a [Mak To make things as seamless as possible please also consider the following steps: -- Update `examples/main.go` with a simple example of the new feature +- Update `examples/functions/main.go` with a simple example of the new feature - Update `README.md` documentation section with any new exported API - Keep 100% code coverage (you can check with `make coverage`) - Squash commits into single units of work with `git rebase -i new-feature` @@ -208,9 +246,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI [codecov-url]: https://app.codecov.io/gh/montanaflynn/stats [codecov-svg]: https://img.shields.io/codecov/c/github/montanaflynn/stats?token=wnw8dActnH -[goreport-url]: https://goreportcard.com/report/github.com/montanaflynn/stats -[goreport-svg]: https://goreportcard.com/badge/github.com/montanaflynn/stats - [godoc-url]: https://godoc.org/github.com/montanaflynn/stats [godoc-svg]: https://godoc.org/github.com/montanaflynn/stats?status.svg diff --git a/vendor/github.com/montanaflynn/stats/clip.go b/vendor/github.com/montanaflynn/stats/clip.go new file mode 100644 index 0000000..94b625a --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/clip.go @@ -0,0 +1,32 @@ +package stats + +// Clip clamps each value in the input slice into the +// inclusive range between min and max. +func Clip(input Float64Data, min, max float64) ([]float64, error) { + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if min > max { + return nil, ErrBounds + } + + c := make([]float64, len(input)) + for i, v := range input { + switch { + case v < min: + c[i] = min + case v > max: + c[i] = max + default: + c[i] = v + } + } + return c, nil +} + +// Clip clamps each value in the input slice into the +// inclusive range between min and max. +func (f Float64Data) Clip(min, max float64) ([]float64, error) { + return Clip(f, min, max) +} diff --git a/vendor/github.com/montanaflynn/stats/coefficient_of_variation.go b/vendor/github.com/montanaflynn/stats/coefficient_of_variation.go new file mode 100644 index 0000000..25789cd --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/coefficient_of_variation.go @@ -0,0 +1,31 @@ +package stats + +import "math" + +// CoefficientOfVariation finds the coefficient of variation of a slice +// of floats, defined as the sample standard deviation divided by the +// mean. This matches the behavior of Python's scipy.stats.variation +// with ddof=1. +// +// The input must not be empty and its mean must not be zero. +func CoefficientOfVariation(input Float64Data) (float64, error) { + if input.Len() == 0 { + return math.NaN(), ErrEmptyInput + } + + // Input is known to be non-empty so the mean and sample + // standard deviation cannot return an error + m, _ := Mean(input) + if m == 0 { + return math.NaN(), ErrZero + } + + sd, _ := StandardDeviationSample(input) + + return sd / m, nil +} + +// CoefficientOfVariation finds the sample standard deviation divided by the mean +func (f Float64Data) CoefficientOfVariation() (float64, error) { + return CoefficientOfVariation(f) +} diff --git a/vendor/github.com/montanaflynn/stats/correlation.go b/vendor/github.com/montanaflynn/stats/correlation.go index 4acab94..1289063 100644 --- a/vendor/github.com/montanaflynn/stats/correlation.go +++ b/vendor/github.com/montanaflynn/stats/correlation.go @@ -2,6 +2,7 @@ package stats import ( "math" + "sort" ) // Correlation describes the degree of relationship between two sets of data @@ -34,27 +35,95 @@ func Pearson(data1, data2 Float64Data) (float64, error) { return Correlation(data1, data2) } +// Spearman calculates the Spearman rank correlation coefficient between two variables. +// It works by ranking the data and then computing the Pearson correlation of the ranks. +// This method handles tied values using fractional (average) ranking. +func Spearman(data1, data2 Float64Data) (float64, error) { + + l1 := data1.Len() + l2 := data2.Len() + + if l1 == 0 || l2 == 0 { + return math.NaN(), EmptyInputErr + } + + if l1 != l2 { + return math.NaN(), SizeErr + } + + ranks1 := rankData(data1) + ranks2 := rankData(data2) + + return Correlation(ranks1, ranks2) +} + +// rankData assigns fractional (average) ranks to the data values. +// Tied values receive the average of the ranks they would have been assigned. +func rankData(data Float64Data) Float64Data { + n := len(data) + + // Create index-value pairs and sort by value + type indexedValue struct { + index int + value float64 + } + + sorted := make([]indexedValue, n) + for i, v := range data { + sorted[i] = indexedValue{i, v} + } + + sort.SliceStable(sorted, func(i, j int) bool { + return sorted[i].value < sorted[j].value + }) + + ranks := make(Float64Data, n) + + // Assign fractional ranks handling ties + for i := 0; i < n; { + j := i + 1 + for j < n && sorted[j].value == sorted[i].value { + j++ + } + + // Average rank for tied values (ranks are 1-based) + avgRank := float64(i+j+1) / 2.0 + for k := i; k < j; k++ { + ranks[sorted[k].index] = avgRank + } + + i = j + } + + return ranks +} + // AutoCorrelation is the correlation of a signal with a delayed copy of itself as a function of delay func AutoCorrelation(data Float64Data, lags int) (float64, error) { if len(data) < 1 { return 0, EmptyInputErr } + if lags < 0 || lags >= len(data) { + return 0, BoundsErr + } + mean, _ := Mean(data) - var result, q float64 + var variance float64 + for _, v := range data { + delta := v - mean + variance += delta * delta + } - for i := 0; i < lags; i++ { - v := (data[0] - mean) * (data[0] - mean) - for i := 1; i < len(data); i++ { - delta0 := data[i-1] - mean - delta1 := data[i] - mean - q += (delta0*delta1 - q) / float64(i+1) - v += (delta1*delta1 - v) / float64(i+1) - } + if variance == 0 { + return 0, nil + } - result = q / v + var covariance float64 + for i := lags; i < len(data); i++ { + covariance += (data[i] - mean) * (data[i-lags] - mean) } - return result, nil + return covariance / variance, nil } diff --git a/vendor/github.com/montanaflynn/stats/cumulative.go b/vendor/github.com/montanaflynn/stats/cumulative.go new file mode 100644 index 0000000..897f827 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/cumulative.go @@ -0,0 +1,76 @@ +package stats + +// CumulativeProduct calculates the cumulative product of the input slice +func CumulativeProduct(input Float64Data) ([]float64, error) { + + if input.Len() == 0 { + return Float64Data{}, ErrEmptyInput + } + + cumProduct := make([]float64, input.Len()) + + for i, val := range input { + if i == 0 { + cumProduct[i] = val + } else { + cumProduct[i] = cumProduct[i-1] * val + } + } + + return cumProduct, nil +} + +// CumulativeMax calculates the cumulative maximum of the input slice +func CumulativeMax(input Float64Data) ([]float64, error) { + + if input.Len() == 0 { + return Float64Data{}, ErrEmptyInput + } + + cumMax := make([]float64, input.Len()) + + for i, val := range input { + if i == 0 || val > cumMax[i-1] { + cumMax[i] = val + } else { + cumMax[i] = cumMax[i-1] + } + } + + return cumMax, nil +} + +// CumulativeMin calculates the cumulative minimum of the input slice +func CumulativeMin(input Float64Data) ([]float64, error) { + + if input.Len() == 0 { + return Float64Data{}, ErrEmptyInput + } + + cumMin := make([]float64, input.Len()) + + for i, val := range input { + if i == 0 || val < cumMin[i-1] { + cumMin[i] = val + } else { + cumMin[i] = cumMin[i-1] + } + } + + return cumMin, nil +} + +// CumulativeProduct calculates the cumulative product of the data +func (f Float64Data) CumulativeProduct() ([]float64, error) { + return CumulativeProduct(f) +} + +// CumulativeMax calculates the cumulative maximum of the data +func (f Float64Data) CumulativeMax() ([]float64, error) { + return CumulativeMax(f) +} + +// CumulativeMin calculates the cumulative minimum of the data +func (f Float64Data) CumulativeMin() ([]float64, error) { + return CumulativeMin(f) +} diff --git a/vendor/github.com/montanaflynn/stats/data.go b/vendor/github.com/montanaflynn/stats/data.go index b86f0d8..1e249b9 100644 --- a/vendor/github.com/montanaflynn/stats/data.go +++ b/vendor/github.com/montanaflynn/stats/data.go @@ -36,10 +36,10 @@ func (f Float64Data) Median() (float64, error) { return Median(f) } // Mode returns the mode of the data func (f Float64Data) Mode() ([]float64, error) { return Mode(f) } -// GeometricMean returns the median of the data +// GeometricMean returns the geometric mean of the data func (f Float64Data) GeometricMean() (float64, error) { return GeometricMean(f) } -// HarmonicMean returns the mode of the data +// HarmonicMean returns the harmonic mean of the data func (f Float64Data) HarmonicMean() (float64, error) { return HarmonicMean(f) } // MedianAbsoluteDeviation the median of the absolute deviations from the dataset median @@ -97,6 +97,11 @@ func (f Float64Data) Pearson(d Float64Data) (float64, error) { return Pearson(f, d) } +// Spearman calculates the Spearman rank correlation coefficient between two variables. +func (f Float64Data) Spearman(d Float64Data) (float64, error) { + return Spearman(f, d) +} + // Quartile returns the three quartile points from a slice of data func (f Float64Data) Quartile(d Float64Data) (Quartiles, error) { return Quartile(d) diff --git a/vendor/github.com/montanaflynn/stats/describe.go b/vendor/github.com/montanaflynn/stats/describe.go index 86b7242..3904ac0 100644 --- a/vendor/github.com/montanaflynn/stats/describe.go +++ b/vendor/github.com/montanaflynn/stats/describe.go @@ -9,6 +9,7 @@ type Description struct { Std float64 Max float64 Min float64 + Range float64 DescriptionPercentiles []descriptionPercentile AllowedNaN bool } @@ -39,6 +40,7 @@ func DescribePercentileFunc(input Float64Data, allowNaN bool, percentiles *[]flo description.Std, _ = StandardDeviation(input) description.Max, _ = Max(input) description.Min, _ = Min(input) + description.Range, _ = Range(input) description.Mean, _ = Mean(input) if percentiles != nil { @@ -60,6 +62,7 @@ Represents the Description instance in a string format with specified number of std 0.82 max 3.00 min 1.00 + range 2.00 25.00% NaN 50.00% 1.50 75.00% 2.50 @@ -73,6 +76,7 @@ func (d *Description) String(decimals int) string { str += fmt.Sprintf("std\t%.*f\n", decimals, d.Std) str += fmt.Sprintf("max\t%.*f\n", decimals, d.Max) str += fmt.Sprintf("min\t%.*f\n", decimals, d.Min) + str += fmt.Sprintf("range\t%.*f\n", decimals, d.Range) for _, percentile := range d.DescriptionPercentiles { str += fmt.Sprintf("%.2f%%\t%.*f\n", percentile.Percentile, decimals, percentile.Value) } diff --git a/vendor/github.com/montanaflynn/stats/diff.go b/vendor/github.com/montanaflynn/stats/diff.go new file mode 100644 index 0000000..7a9bdfc --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/diff.go @@ -0,0 +1,48 @@ +package stats + +// Diff calculates the successive differences of the input slice, +// returning input[i] - input[i-1] for each i in 1..len(input)-1. +// The output has length len(input) - 1; a single-element input +// returns an empty slice. +func Diff(input Float64Data) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + diff := make([]float64, input.Len()-1) + + for i := 1; i < input.Len(); i++ { + diff[i-1] = input[i] - input[i-1] + } + + return diff, nil +} + +// PercentChange calculates the fractional change between successive +// elements of the input slice, returning +// (input[i] - input[i-1]) / input[i-1] for each i in 1..len(input)-1. +// The output has length len(input) - 1; a single-element input +// returns an empty slice. A zero denominator follows IEEE 754 +// semantics, yielding +Inf, -Inf, or NaN (for 0/0), matching the +// behavior of pandas pct_change. +func PercentChange(input Float64Data) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + change := make([]float64, input.Len()-1) + + for i := 1; i < input.Len(); i++ { + change[i-1] = (input[i] - input[i-1]) / input[i-1] + } + + return change, nil +} + +// Diff returns the successive differences of the data +func (f Float64Data) Diff() ([]float64, error) { return Diff(f) } + +// PercentChange returns the fractional change between successive elements of the data +func (f Float64Data) PercentChange() ([]float64, error) { return PercentChange(f) } diff --git a/vendor/github.com/montanaflynn/stats/ewma.go b/vendor/github.com/montanaflynn/stats/ewma.go new file mode 100644 index 0000000..a0b59a5 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/ewma.go @@ -0,0 +1,32 @@ +package stats + +// EWMA calculates the exponentially weighted moving average of the input +// with smoothing factor alpha. The first output equals the first input and +// each subsequent entry is alpha*input[i] + (1-alpha)*output[i-1], so the +// result has the same length as the input. The alpha must satisfy +// 0 < alpha <= 1 or ErrBounds is returned. An empty input returns +// ErrEmptyInput. +func EWMA(input Float64Data, alpha float64) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if alpha <= 0 || alpha > 1 { + return nil, ErrBounds + } + + output := make([]float64, input.Len()) + + output[0] = input[0] + for i := 1; i < input.Len(); i++ { + output[i] = alpha*input[i] + (1-alpha)*output[i-1] + } + + return output, nil +} + +// EWMA returns the exponentially weighted moving average of the data with smoothing factor alpha +func (f Float64Data) EWMA(alpha float64) ([]float64, error) { + return EWMA(f, alpha) +} diff --git a/vendor/github.com/montanaflynn/stats/extremes.go b/vendor/github.com/montanaflynn/stats/extremes.go new file mode 100644 index 0000000..dd31581 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/extremes.go @@ -0,0 +1,72 @@ +package stats + +// ArgMax finds the index of the highest number in a slice, +// returning the first occurrence in the case of ties +func ArgMax(input Float64Data) (int, error) { + + // Return an error if there are no numbers + if input.Len() == 0 { + return -1, ErrEmptyInput + } + + // Track the index of the highest value seen so far + index := 0 + + // Loop and replace with strictly higher values only, + // which keeps the first occurrence on ties + for i := 1; i < input.Len(); i++ { + if input.Get(i) > input.Get(index) { + index = i + } + } + + return index, nil +} + +// ArgMin finds the index of the lowest number in a slice, +// returning the first occurrence in the case of ties +func ArgMin(input Float64Data) (int, error) { + + // Return an error if there are no numbers + if input.Len() == 0 { + return -1, ErrEmptyInput + } + + // Track the index of the lowest value seen so far + index := 0 + + // Loop and replace with strictly lower values only, + // which keeps the first occurrence on ties + for i := 1; i < input.Len(); i++ { + if input.Get(i) < input.Get(index) { + index = i + } + } + + return index, nil +} + +// Range finds the difference between the highest and +// lowest numbers in a slice +func Range(input Float64Data) (float64, error) { + + // Return an error if there are no numbers + max, err := Max(input) + if err != nil { + return max, ErrEmptyInput + } + + // Disregard error, since Max would have already returned it + min, _ := Min(input) + + return max - min, nil +} + +// ArgMax returns the index of the highest number in the data +func (f Float64Data) ArgMax() (int, error) { return ArgMax(f) } + +// ArgMin returns the index of the lowest number in the data +func (f Float64Data) ArgMin() (int, error) { return ArgMin(f) } + +// Range returns the difference between the highest and lowest numbers in the data +func (f Float64Data) Range() (float64, error) { return Range(f) } diff --git a/vendor/github.com/montanaflynn/stats/histogram.go b/vendor/github.com/montanaflynn/stats/histogram.go new file mode 100644 index 0000000..c2ebb8d --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/histogram.go @@ -0,0 +1,57 @@ +package stats + +import "sort" + +// Histogram calculates the histogram of a slice using the given +// number of equal-width bins over [min, max], returning the count +// of values in each bin along with the bins+1 bin edges. Each bin +// is half-open [edges[i], edges[i+1]) except the last, which also +// includes the maximum value. +func Histogram(input Float64Data, bins int) ([]int, []float64, error) { + + if input.Len() == 0 { + return nil, nil, ErrEmptyInput + } + + if bins < 1 { + return nil, nil, ErrBounds + } + + // Disregard errors, since input is not empty + min, _ := Min(input) + max, _ := Max(input) + + // Expand the range by 0.5 on each side like + // numpy when all of the values are equal + if min == max { + min -= 0.5 + max += 0.5 + } + + // Build bins+1 equal-width bin edges from min to max + width := (max - min) / float64(bins) + edges := make([]float64, bins+1) + for i := range edges { + edges[i] = min + width*float64(i) + } + edges[bins] = max + + // Count each value into the last bin whose left + // edge does not exceed it, so the maximum value + // lands in the final closed bin + counts := make([]int, bins) + for _, v := range input { + i := sort.Search(len(edges), func(i int) bool { return edges[i] > v }) - 1 + if i == bins { + i-- + } + counts[i]++ + } + + return counts, edges, nil +} + +// Histogram returns the counts and equal-width bin edges of the data +func (f Float64Data) Histogram(bins int) ([]int, []float64, error) { + return Histogram(f, bins) +} diff --git a/vendor/github.com/montanaflynn/stats/interp.go b/vendor/github.com/montanaflynn/stats/interp.go new file mode 100644 index 0000000..86a4c3a --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/interp.go @@ -0,0 +1,46 @@ +package stats + +import "sort" + +// Interp calculates the one-dimensional piecewise-linear interpolant to a +// function with given discrete data points (xp, fp), evaluated at each x. +// Values of x below xp[0] return fp[0] and values above xp[len(xp)-1] return +// fp[len(xp)-1], so no extrapolation is performed. Unlike numpy's interp, +// which silently returns nonsense for unsorted coordinates, xp must be +// strictly increasing or ErrBounds is returned. An empty x or xp returns +// ErrEmptyInput and xp and fp of different lengths return ErrSize. +func Interp(x, xp, fp Float64Data) ([]float64, error) { + + if x.Len() == 0 || xp.Len() == 0 { + return nil, ErrEmptyInput + } + + if xp.Len() != fp.Len() { + return nil, ErrSize + } + + for i := 1; i < xp.Len(); i++ { + if xp[i] <= xp[i-1] { + return nil, ErrBounds + } + } + + output := make([]float64, x.Len()) + + for i, xv := range x { + switch { + case xv <= xp[0]: + output[i] = fp[0] + case xv >= xp[xp.Len()-1]: + output[i] = fp[fp.Len()-1] + default: + // The first index with xp[j] >= xv, which the clamping + // above guarantees is within [1, len(xp)-1] + j := sort.SearchFloat64s(xp, xv) + t := (xv - xp[j-1]) / (xp[j] - xp[j-1]) + output[i] = fp[j-1] + t*(fp[j]-fp[j-1]) + } + } + + return output, nil +} diff --git a/vendor/github.com/montanaflynn/stats/kendall.go b/vendor/github.com/montanaflynn/stats/kendall.go new file mode 100644 index 0000000..bba7928 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/kendall.go @@ -0,0 +1,57 @@ +package stats + +import "math" + +// KendallTau calculates Kendall's tau-b rank correlation coefficient +// between two variables. Tau-b corrects for ties, matching the values +// produced by SciPy's kendalltau and pandas' corr(method="kendall"). +// Pairs are compared with a simple O(n^2) loop for clarity. +func KendallTau(data1, data2 Float64Data) (float64, error) { + + l1 := data1.Len() + l2 := data2.Len() + + if l1 == 0 || l2 == 0 { + return math.NaN(), ErrEmptyInput + } + + if l1 != l2 { + return math.NaN(), ErrSize + } + + // Count concordant and discordant pairs along with pairs + // tied only in the first or only in the second variable. + var concordant, discordant, tiedX, tiedY float64 + for i := 0; i < l1; i++ { + for j := i + 1; j < l1; j++ { + dx := data1[i] - data1[j] + dy := data2[i] - data2[j] + switch { + case dx == 0 && dy == 0: + // Pairs tied in both variables are excluded + case dx == 0: + tiedX++ + case dy == 0: + tiedY++ + case (dx > 0) == (dy > 0): + concordant++ + default: + discordant++ + } + } + } + + // tau-b = (C - D) / sqrt((C + D + Tx) * (C + D + Ty)) + denominator := math.Sqrt((concordant + discordant + tiedX) * (concordant + discordant + tiedY)) + if denominator == 0 { + return 0, nil + } + + return (concordant - discordant) / denominator, nil +} + +// KendallTau calculates Kendall's tau-b rank correlation coefficient +// between two variables. +func (f Float64Data) KendallTau(d Float64Data) (float64, error) { + return KendallTau(f, d) +} diff --git a/vendor/github.com/montanaflynn/stats/kurtosis.go b/vendor/github.com/montanaflynn/stats/kurtosis.go new file mode 100644 index 0000000..4a83b20 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/kurtosis.go @@ -0,0 +1,70 @@ +package stats + +import "math" + +// Kurtosis computes the population excess kurtosis of the dataset +func Kurtosis(input Float64Data) (float64, error) { + return PopulationKurtosis(input) +} + +// PopulationKurtosis computes the population excess kurtosis (Fisher +// definition) using the fourth central moment normalized by the squared +// variance, so a normal distribution has a kurtosis of zero. +func PopulationKurtosis(input Float64Data) (float64, error) { + if input.Len() < 2 { + return math.NaN(), ErrEmptyInput + } + + mean, _ := Mean(input) + + // Compute sums of squared and fourth-power differences from the mean + var sumOfSquares, sumOfFourths float64 + for _, v := range input { + d := v - mean + d2 := d * d + sumOfSquares += d2 + sumOfFourths += d2 * d2 + } + + if sumOfSquares == 0 { + return math.NaN(), ErrZero + } + + n := float64(input.Len()) + variance := sumOfSquares / n + + return (sumOfFourths/n)/(variance*variance) - 3.0, nil +} + +// SampleKurtosis computes the bias-corrected sample excess kurtosis, +// matching pandas .kurt() and scipy.stats.kurtosis with bias=False. +func SampleKurtosis(input Float64Data) (float64, error) { + n := input.Len() + if n < 4 { + return math.NaN(), ErrEmptyInput + } + + g2, err := PopulationKurtosis(input) + if err != nil { + return math.NaN(), err + } + + // Bias-corrected: G2 = ((n+1)*g2 + 6) * (n-1) / ((n-2)*(n-3)) + nf := float64(n) + return ((nf+1)*g2 + 6) * (nf - 1) / ((nf - 2) * (nf - 3)), nil +} + +// Kurtosis finds the population excess kurtosis of a slice of floats +func (f Float64Data) Kurtosis() (float64, error) { + return Kurtosis(f) +} + +// PopulationKurtosis finds the population excess kurtosis of a slice of floats +func (f Float64Data) PopulationKurtosis() (float64, error) { + return PopulationKurtosis(f) +} + +// SampleKurtosis finds the bias-corrected sample excess kurtosis of a slice of floats +func (f Float64Data) SampleKurtosis() (float64, error) { + return SampleKurtosis(f) +} diff --git a/vendor/github.com/montanaflynn/stats/mean.go b/vendor/github.com/montanaflynn/stats/mean.go index a78d299..de4f6a6 100644 --- a/vendor/github.com/montanaflynn/stats/mean.go +++ b/vendor/github.com/montanaflynn/stats/mean.go @@ -22,18 +22,19 @@ func GeometricMean(input Float64Data) (float64, error) { return math.NaN(), EmptyInputErr } - // Get the product of all the numbers + // Get the sum of all the numbers natural logs and return an + // error for values that cannot be included in geometric mean var p float64 for _, n := range input { - if p == 0 { - p = n - } else { - p *= n + if n < 0 { + return math.NaN(), NegativeErr + } else if n == 0 { + return math.NaN(), ZeroErr } + p += math.Log(n) } - // Calculate the geometric mean - return math.Pow(p, 1/float64(l)), nil + return math.Exp(p / float64(l)), nil } // HarmonicMean gets the harmonic mean for a slice of numbers diff --git a/vendor/github.com/montanaflynn/stats/moving.go b/vendor/github.com/montanaflynn/stats/moving.go new file mode 100644 index 0000000..ce18f88 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/moving.go @@ -0,0 +1,125 @@ +package stats + +// MovingMedian calculates the rolling median of the input over a trailing +// window. Only fully-populated windows produce output, so the result has +// len(input)-window+1 entries and entry i is the median of input[i : i+window]. +// The window must satisfy 1 <= window <= len(input) or ErrBounds is +// returned. An empty input returns ErrEmptyInput. +func MovingMedian(input Float64Data, window int) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if window < 1 || window > input.Len() { + return nil, ErrBounds + } + + output := make([]float64, input.Len()-window+1) + + for i := range output { + // Median cannot fail here since every window is non-empty + median, _ := Median(input[i : i+window]) + output[i] = median + } + + return output, nil +} + +// MovingMin calculates the rolling minimum of the input over a trailing +// window. Only fully-populated windows produce output, so the result has +// len(input)-window+1 entries and entry i is the minimum of +// input[i : i+window]. The window must satisfy 1 <= window <= len(input) or +// ErrBounds is returned. An empty input returns ErrEmptyInput. +func MovingMin(input Float64Data, window int) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if window < 1 || window > input.Len() { + return nil, ErrBounds + } + + output := make([]float64, input.Len()-window+1) + + for i := range output { + // Min cannot fail here since every window is non-empty + min, _ := Min(input[i : i+window]) + output[i] = min + } + + return output, nil +} + +// MovingMax calculates the rolling maximum of the input over a trailing +// window. Only fully-populated windows produce output, so the result has +// len(input)-window+1 entries and entry i is the maximum of +// input[i : i+window]. The window must satisfy 1 <= window <= len(input) or +// ErrBounds is returned. An empty input returns ErrEmptyInput. +func MovingMax(input Float64Data, window int) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if window < 1 || window > input.Len() { + return nil, ErrBounds + } + + output := make([]float64, input.Len()-window+1) + + for i := range output { + // Max cannot fail here since every window is non-empty + max, _ := Max(input[i : i+window]) + output[i] = max + } + + return output, nil +} + +// MovingSum calculates the rolling sum of the input over a trailing +// window. Only fully-populated windows produce output, so the result has +// len(input)-window+1 entries and entry i is the sum of input[i : i+window]. +// The window must satisfy 1 <= window <= len(input) or ErrBounds is +// returned. An empty input returns ErrEmptyInput. +func MovingSum(input Float64Data, window int) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if window < 1 || window > input.Len() { + return nil, ErrBounds + } + + output := make([]float64, input.Len()-window+1) + + for i := range output { + // Sum cannot fail here since every window is non-empty + sum, _ := Sum(input[i : i+window]) + output[i] = sum + } + + return output, nil +} + +// MovingMedian returns the rolling median of the data over a trailing window +func (f Float64Data) MovingMedian(window int) ([]float64, error) { + return MovingMedian(f, window) +} + +// MovingMin returns the rolling minimum of the data over a trailing window +func (f Float64Data) MovingMin(window int) ([]float64, error) { + return MovingMin(f, window) +} + +// MovingMax returns the rolling maximum of the data over a trailing window +func (f Float64Data) MovingMax(window int) ([]float64, error) { + return MovingMax(f, window) +} + +// MovingSum returns the rolling sum of the data over a trailing window +func (f Float64Data) MovingSum(window int) ([]float64, error) { + return MovingSum(f, window) +} diff --git a/vendor/github.com/montanaflynn/stats/norm.go b/vendor/github.com/montanaflynn/stats/norm.go index 4eb8eb8..620c5ac 100644 --- a/vendor/github.com/montanaflynn/stats/norm.go +++ b/vendor/github.com/montanaflynn/stats/norm.go @@ -7,6 +7,12 @@ import ( "time" ) +// NormSample generates random samples from a normal distribution +// with the given mean (loc) and standard deviation (scale). +func NormSample(loc float64, scale float64, size int) []float64 { + return NormBoxMullerRvs(loc, scale, size) +} + // NormPpfRvs generates random variates using the Point Percentile Function. // For more information please visit: https://demonstrations.wolfram.com/TheMethodOfInverseTransforms/ func NormPpfRvs(loc float64, scale float64, size int) []float64 { diff --git a/vendor/github.com/montanaflynn/stats/percentile_of_score.go b/vendor/github.com/montanaflynn/stats/percentile_of_score.go new file mode 100644 index 0000000..a958c95 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/percentile_of_score.go @@ -0,0 +1,31 @@ +package stats + +import "math" + +// PercentileOfScore calculates the percentile rank of a score +// relative to a slice of floats, defined as the percentage of +// values strictly below the score plus half the percentage of +// values equal to the score. The result is between 0 and 100. +// This matches the behavior of Python's +// scipy.stats.percentileofscore with kind="rank". +func PercentileOfScore(input Float64Data, score float64) (float64, error) { + if input.Len() == 0 { + return math.NaN(), ErrEmptyInput + } + + var below, equal float64 + for _, v := range input { + if v < score { + below++ + } else if v == score { + equal++ + } + } + + return 100 * (below + 0.5*equal) / float64(input.Len()), nil +} + +// PercentileOfScore calculates the percentile rank of a score relative to the data +func (f Float64Data) PercentileOfScore(score float64) (float64, error) { + return PercentileOfScore(f, score) +} diff --git a/vendor/github.com/montanaflynn/stats/percentile_weighted.go b/vendor/github.com/montanaflynn/stats/percentile_weighted.go new file mode 100644 index 0000000..beb09a0 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/percentile_weighted.go @@ -0,0 +1,69 @@ +package stats + +import ( + "math" + "sort" +) + +// PercentileWeighted finds the weighted percentile of a slice of floats +// using the weighted empirical CDF (inverse CDF / nearest-rank method). +// +// For a given percent p, it returns the smallest data value x such that +// the cumulative weight of all values <= x is at least p% of the total +// weight. This matches the behavior of Python's statsmodels +// DescrStatsW.quantile. +// +// The data and weights slices must be the same length. Weights must be +// non-negative and at least one weight must be positive. The percent +// parameter must be between 0 and 100 (exclusive). +func PercentileWeighted(data, weights Float64Data, percent float64) (percentile float64, err error) { + l := data.Len() + if l == 0 { + return math.NaN(), ErrEmptyInput + } + + if weights.Len() != l { + return math.NaN(), ErrSize + } + + if percent <= 0 || percent > 100 { + return math.NaN(), ErrBounds + } + + // Build sorted pairs by data value + type pair struct { + value float64 + weight float64 + } + pairs := make([]pair, l) + totalWeight := 0.0 + for i := 0; i < l; i++ { + if weights[i] < 0 { + return math.NaN(), ErrNegative + } + pairs[i] = pair{data[i], weights[i]} + totalWeight += weights[i] + } + + if totalWeight == 0 { + return math.NaN(), ErrBounds + } + + sort.Slice(pairs, func(i, j int) bool { + return pairs[i].value < pairs[j].value + }) + + // Find the smallest value where cumulative weight >= target + target := (percent / 100) * totalWeight + cumWeight := 0.0 + result := pairs[l-1].value + for i := 0; i < l; i++ { + cumWeight += pairs[i].weight + if cumWeight >= target { + result = pairs[i].value + break + } + } + + return result, nil +} diff --git a/vendor/github.com/montanaflynn/stats/product.go b/vendor/github.com/montanaflynn/stats/product.go new file mode 100644 index 0000000..d5ded82 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/product.go @@ -0,0 +1,26 @@ +package stats + +import "math" + +// Product calculates the product of a slice of floats by +// multiplying the values from left to right. It is the scalar +// counterpart of CumulativeProduct. Large inputs can overflow +// to Inf; use GeometricMean for an overflow-safe summary of +// multiplicative data. +func Product(input Float64Data) (float64, error) { + if input.Len() == 0 { + return math.NaN(), ErrEmptyInput + } + + product := 1.0 + for _, v := range input { + product *= v + } + + return product, nil +} + +// Product calculates the product of the data +func (f Float64Data) Product() (float64, error) { + return Product(f) +} diff --git a/vendor/github.com/montanaflynn/stats/rank.go b/vendor/github.com/montanaflynn/stats/rank.go new file mode 100644 index 0000000..0e9f861 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/rank.go @@ -0,0 +1,16 @@ +package stats + +// Rank assigns fractional (average) ranks to the input values. +// Ranks are 1-based and tied values receive the average of the +// ranks they would have been assigned. +func Rank(input Float64Data) ([]float64, error) { + if input.Len() == 0 { + return nil, ErrEmptyInput + } + return rankData(input), nil +} + +// Rank assigns fractional (average) ranks to the input values +func (f Float64Data) Rank() ([]float64, error) { + return Rank(f) +} diff --git a/vendor/github.com/montanaflynn/stats/rescale.go b/vendor/github.com/montanaflynn/stats/rescale.go new file mode 100644 index 0000000..814fce0 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/rescale.go @@ -0,0 +1,29 @@ +package stats + +// Rescale normalizes the input values to the range of 0 to 1 +// by subtracting the minimum and dividing by the range, +// also known as min-max normalization. +func Rescale(input Float64Data) ([]float64, error) { + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + min, _ := Min(input) + max, _ := Max(input) + + if max == min { + return nil, ErrZero + } + + r := make([]float64, len(input)) + for i, v := range input { + r[i] = (v - min) / (max - min) + } + return r, nil +} + +// Rescale normalizes the input values to the range of 0 to 1 +// by subtracting the minimum and dividing by the range +func (f Float64Data) Rescale() ([]float64, error) { + return Rescale(f) +} diff --git a/vendor/github.com/montanaflynn/stats/rms.go b/vendor/github.com/montanaflynn/stats/rms.go new file mode 100644 index 0000000..7599e3d --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/rms.go @@ -0,0 +1,23 @@ +package stats + +import "math" + +// RMS calculates the root mean square of a slice of floats, +// defined as the square root of the mean of the squared values. +func RMS(input Float64Data) (float64, error) { + if input.Len() == 0 { + return math.NaN(), ErrEmptyInput + } + + var sumSquares float64 + for _, v := range input { + sumSquares += v * v + } + + return math.Sqrt(sumSquares / float64(input.Len())), nil +} + +// RMS calculates the root mean square of the data +func (f Float64Data) RMS() (float64, error) { + return RMS(f) +} diff --git a/vendor/github.com/montanaflynn/stats/rolling.go b/vendor/github.com/montanaflynn/stats/rolling.go new file mode 100644 index 0000000..571eb59 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/rolling.go @@ -0,0 +1,65 @@ +package stats + +// MovingAverage calculates the rolling mean of the input over a trailing +// window. Only fully-populated windows produce output, so the result has +// len(input)-window+1 entries and entry i is the mean of input[i : i+window]. +// The window must satisfy 1 <= window <= len(input) or ErrBounds is +// returned. An empty input returns ErrEmptyInput. +func MovingAverage(input Float64Data, window int) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if window < 1 || window > input.Len() { + return nil, ErrBounds + } + + output := make([]float64, input.Len()-window+1) + + for i := range output { + // Mean cannot fail here since every window is non-empty + mean, _ := Mean(input[i : i+window]) + output[i] = mean + } + + return output, nil +} + +// MovingStdDev calculates the rolling sample standard deviation of the input +// over a trailing window. Only fully-populated windows produce output, so the +// result has len(input)-window+1 entries and entry i is the sample standard +// deviation of input[i : i+window]. The window must satisfy +// 2 <= window <= len(input) or ErrBounds is returned, since the sample +// standard deviation of a single value is undefined. An empty input returns +// ErrEmptyInput. +func MovingStdDev(input Float64Data, window int) ([]float64, error) { + + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + if window < 2 || window > input.Len() { + return nil, ErrBounds + } + + output := make([]float64, input.Len()-window+1) + + for i := range output { + // StandardDeviationSample cannot fail here since every window is non-empty + sdev, _ := StandardDeviationSample(input[i : i+window]) + output[i] = sdev + } + + return output, nil +} + +// MovingAverage returns the rolling mean of the data over a trailing window +func (f Float64Data) MovingAverage(window int) ([]float64, error) { + return MovingAverage(f, window) +} + +// MovingStdDev returns the rolling sample standard deviation of the data over a trailing window +func (f Float64Data) MovingStdDev(window int) ([]float64, error) { + return MovingStdDev(f, window) +} diff --git a/vendor/github.com/montanaflynn/stats/round.go b/vendor/github.com/montanaflynn/stats/round.go index b66779c..7e122a6 100644 --- a/vendor/github.com/montanaflynn/stats/round.go +++ b/vendor/github.com/montanaflynn/stats/round.go @@ -4,35 +4,9 @@ import "math" // Round a float to a specific decimal place or precision func Round(input float64, places int) (rounded float64, err error) { - - // If the float is not a number if math.IsNaN(input) { return math.NaN(), NaNErr } - - // Find out the actual sign and correct the input for later - sign := 1.0 - if input < 0 { - sign = -1 - input *= -1 - } - - // Use the places arg to get the amount of precision wanted precision := math.Pow(10, float64(places)) - - // Find the decimal place we are looking to round - digit := input * precision - - // Get the actual decimal number as a fraction to be compared - _, decimal := math.Modf(digit) - - // If the decimal is less than .5 we round down otherwise up - if decimal >= 0.5 { - rounded = math.Ceil(digit) - } else { - rounded = math.Floor(digit) - } - - // Finally we do the math to actually create a rounded number - return rounded / precision * sign, nil + return math.Round(input*precision) / precision, nil } diff --git a/vendor/github.com/montanaflynn/stats/sem.go b/vendor/github.com/montanaflynn/stats/sem.go new file mode 100644 index 0000000..111b46e --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/sem.go @@ -0,0 +1,24 @@ +package stats + +import "math" + +// SEM calculates the standard error of the mean of a slice +// of floats, defined as the sample standard deviation divided +// by the square root of the sample size. This matches the +// behavior of Python's scipy.stats.sem with ddof=1. +func SEM(input Float64Data) (float64, error) { + if input.Len() == 0 { + return math.NaN(), ErrEmptyInput + } + + // Input is known to be non-empty so the sample standard + // deviation cannot return an error + sd, _ := StandardDeviationSample(input) + + return sd / math.Sqrt(float64(input.Len())), nil +} + +// SEM calculates the standard error of the mean of the data +func (f Float64Data) SEM() (float64, error) { + return SEM(f) +} diff --git a/vendor/github.com/montanaflynn/stats/trimmed_mean.go b/vendor/github.com/montanaflynn/stats/trimmed_mean.go new file mode 100644 index 0000000..0a99595 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/trimmed_mean.go @@ -0,0 +1,38 @@ +package stats + +import "math" + +// TrimmedMean finds the mean of a slice of floats after removing a +// fraction of the smallest and largest values. This matches the +// behavior of Python's scipy.stats.trim_mean. +// +// The percent parameter is the fraction removed from each tail and +// must be in the range [0, 0.5). The number of elements trimmed from +// each tail is floor(len(input) * percent). A percent of zero returns +// the same result as Mean. +func TrimmedMean(input Float64Data, percent float64) (float64, error) { + l := input.Len() + if l == 0 { + return math.NaN(), ErrEmptyInput + } + + // Reject percents outside [0, 0.5) including NaN. Since percent is + // strictly below 0.5 at least one element always remains after + // trimming floor(l * percent) elements from each tail. + if !(percent >= 0 && percent < 0.5) { + return math.NaN(), ErrBounds + } + + sorted := sortedCopy(input) + + // Number of elements removed from each tail + k := int(math.Floor(float64(l) * percent)) + + return Mean(sorted[k : l-k]) +} + +// TrimmedMean finds the mean of the data after removing a fraction of +// the smallest and largest values from each tail +func (f Float64Data) TrimmedMean(percent float64) (float64, error) { + return TrimmedMean(f, percent) +} diff --git a/vendor/github.com/montanaflynn/stats/ttest.go b/vendor/github.com/montanaflynn/stats/ttest.go new file mode 100644 index 0000000..f36ea32 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/ttest.go @@ -0,0 +1,128 @@ +package stats + +import "math" + +// TTest performs a one-sample or two-sample (independent) Student's t-test. +// +// For a one-sample t-test, pass the sample data as data1, nil for data2, +// and the expected population mean as populationMean. +// +// For a two-sample independent t-test (assuming equal variance), pass both +// sample datasets. The populationMean parameter is ignored in this case. +// +// Returns the t statistic and the two-tailed p-value. +// +// https://en.wikipedia.org/wiki/Student%27s_t-test +func TTest(data1, data2 Float64Data, populationMean float64) (t float64, pvalue float64, err error) { + + n1 := data1.Len() + if n1 == 0 { + return math.NaN(), math.NaN(), ErrEmptyInput + } + + mean1, _ := Mean(data1) + + // Two-sample independent t-test (equal variance) + if data2 != nil && data2.Len() > 0 { + n2 := data2.Len() + + if n1+n2 < 3 { + return math.NaN(), math.NaN(), ErrBounds + } + + mean2, _ := Mean(data2) + var1, _ := SampleVariance(data1) + var2, _ := SampleVariance(data2) + + df := float64(n1 + n2 - 2) + pooledVar := (float64(n1-1)*var1 + float64(n2-1)*var2) / df + se := math.Sqrt(pooledVar * (1.0/float64(n1) + 1.0/float64(n2))) + t = (mean1 - mean2) / se + pvalue = 2 * tSf(math.Abs(t), df) + } else { + // One-sample t-test + if n1 < 2 { + return math.NaN(), math.NaN(), ErrBounds + } + + sd, _ := StandardDeviationSample(data1) + if sd == 0 { + if mean1 == populationMean { + return 0, 1.0, nil + } + return math.NaN(), math.NaN(), ErrBounds + } + se := sd / math.Sqrt(float64(n1)) + t = (mean1 - populationMean) / se + df := float64(n1 - 1) + pvalue = 2 * tSf(math.Abs(t), df) + } + + return t, pvalue, nil +} + +// tSf is the survival function for Student's t-distribution. +// It computes 1 - CDF(t, df) using the regularized incomplete beta function. +func tSf(t float64, df float64) float64 { + x := df / (df + t*t) + return 0.5 * regIncBeta(df/2.0, 0.5, x) +} + +// regIncBeta computes the regularized incomplete beta function I_x(a, b) +// using a continued fraction approximation (Lentz's algorithm). +func regIncBeta(a, b, x float64) float64 { + if x == 0 || x == 1 { + return x + } + + lbeta := lgammaBeta(a, b) + front := math.Exp(math.Log(x)*a + math.Log(1-x)*b - lbeta) / a + + // Use Lentz's continued fraction algorithm + f := 1.0 + c := 1.0 + d := clampTiny(1.0 - (a+b)*x/(a+1)) + d = 1.0 / d + f = d + + for i := 1; i <= 200; i++ { + m := float64(i) + // Numerator for even step + num := m * (b - m) * x / ((a + 2*m - 1) * (a + 2*m)) + d = clampTiny(1.0 + num*d) + c = clampTiny(1.0 + num/c) + d = 1.0 / d + f *= c * d + + // Numerator for odd step + num = -(a + m) * (a + b + m) * x / ((a + 2*m) * (a + 2*m + 1)) + d = clampTiny(1.0 + num*d) + c = clampTiny(1.0 + num/c) + d = 1.0 / d + delta := c * d + f *= delta + + if math.Abs(delta-1.0) < 1e-10 { + break + } + } + + return front * f +} + +// clampTiny prevents division by zero in Lentz's continued fraction +// algorithm by replacing near-zero values with a small constant. +func clampTiny(v float64) float64 { + if math.Abs(v) < 1e-30 { + return 1e-30 + } + return v +} + +// lgammaBeta computes log(Beta(a, b)) = log(Gamma(a)) + log(Gamma(b)) - log(Gamma(a+b)) +func lgammaBeta(a, b float64) float64 { + la, _ := math.Lgamma(a) + lb, _ := math.Lgamma(b) + lab, _ := math.Lgamma(a + b) + return la + lb - lab +} diff --git a/vendor/github.com/montanaflynn/stats/weighted_mean.go b/vendor/github.com/montanaflynn/stats/weighted_mean.go new file mode 100644 index 0000000..b2c20c3 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/weighted_mean.go @@ -0,0 +1,42 @@ +package stats + +import "math" + +// WeightedMean finds the weighted mean of a slice of floats, defined as +// the sum of each data value multiplied by its weight divided by the sum +// of all the weights. This matches the behavior of Python's +// numpy.average with the weights argument. +// +// The data and weights slices must be the same length. Weights must be +// non-negative and at least one weight must be positive. +func WeightedMean(data, weights Float64Data) (float64, error) { + l := data.Len() + if l == 0 { + return math.NaN(), ErrEmptyInput + } + + if weights.Len() != l { + return math.NaN(), ErrSize + } + + weightedSum := 0.0 + totalWeight := 0.0 + for i := 0; i < l; i++ { + if weights[i] < 0 { + return math.NaN(), ErrNegative + } + weightedSum += data[i] * weights[i] + totalWeight += weights[i] + } + + if totalWeight == 0 { + return math.NaN(), ErrZero + } + + return weightedSum / totalWeight, nil +} + +// WeightedMean finds the weighted mean of the data using the given weights +func (f Float64Data) WeightedMean(weights Float64Data) (float64, error) { + return WeightedMean(f, weights) +} diff --git a/vendor/github.com/montanaflynn/stats/winsorize.go b/vendor/github.com/montanaflynn/stats/winsorize.go new file mode 100644 index 0000000..87776be --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/winsorize.go @@ -0,0 +1,50 @@ +package stats + +import "math" + +// Winsorize limits the effect of outliers in a slice of floats by +// clamping a fraction of the smallest and largest values. This matches +// the behavior of Python's scipy.stats.mstats.winsorize with symmetric +// limits. +// +// The percent parameter is the fraction clamped in each tail and must +// be in the range [0, 0.5). With k = floor(len(input) * percent), +// values below the k-th smallest value are set to it and values above +// the k-th largest value are set to it. The returned slice preserves +// the original element order and a percent of zero returns a copy of +// the input. +func Winsorize(input Float64Data, percent float64) ([]float64, error) { + l := input.Len() + if l == 0 { + return nil, ErrEmptyInput + } + + // Reject percents outside [0, 0.5) including NaN + if !(percent >= 0 && percent < 0.5) { + return nil, ErrBounds + } + + sorted := sortedCopy(input) + + // Number of elements clamped in each tail + k := int(math.Floor(float64(l) * percent)) + lower := sorted[k] + upper := sorted[l-1-k] + + output := copyslice(input) + for i, v := range output { + if v < lower { + output[i] = lower + } else if v > upper { + output[i] = upper + } + } + + return output, nil +} + +// Winsorize returns a copy of the data with a fraction of the smallest +// and largest values in each tail clamped +func (f Float64Data) Winsorize(percent float64) ([]float64, error) { + return Winsorize(f, percent) +} diff --git a/vendor/github.com/montanaflynn/stats/zscore.go b/vendor/github.com/montanaflynn/stats/zscore.go new file mode 100644 index 0000000..bc256f3 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/zscore.go @@ -0,0 +1,29 @@ +package stats + +// ZScore standardizes the input values by subtracting the mean +// and dividing by the sample standard deviation, returning the +// number of standard deviations each value is from the mean. +func ZScore(input Float64Data) ([]float64, error) { + if input.Len() == 0 { + return nil, ErrEmptyInput + } + + m, _ := Mean(input) + sd, _ := StandardDeviationSample(input) + + if sd == 0 { + return nil, ErrZero + } + + z := make([]float64, len(input)) + for i, v := range input { + z[i] = (v - m) / sd + } + return z, nil +} + +// ZScore standardizes the input values by subtracting the mean +// and dividing by the sample standard deviation +func (f Float64Data) ZScore() ([]float64, error) { + return ZScore(f) +} diff --git a/vendor/github.com/montanaflynn/stats/ztest.go b/vendor/github.com/montanaflynn/stats/ztest.go new file mode 100644 index 0000000..eb85553 --- /dev/null +++ b/vendor/github.com/montanaflynn/stats/ztest.go @@ -0,0 +1,50 @@ +package stats + +import "math" + +// ZTest performs a one-sample or two-sample Z-test. +// +// For a one-sample Z-test, pass the sample data as data1, nil for data2, +// the known population mean as populationMean, and the known population +// standard deviation as populationStdDev. +// +// For a two-sample Z-test, pass both sample datasets and the known population +// standard deviations. The populationMean parameter is ignored in this case. +// +// Returns the Z statistic and the two-tailed p-value. +// +// https://en.wikipedia.org/wiki/Z-test +func ZTest(data1, data2 Float64Data, populationMean, populationStdDev float64) (z float64, pvalue float64, err error) { + + n1 := data1.Len() + if n1 == 0 { + return math.NaN(), math.NaN(), ErrEmptyInput + } + + mean1, _ := Mean(data1) + + // Two-sample Z-test + if data2 != nil && data2.Len() > 0 { + n2 := data2.Len() + mean2, _ := Mean(data2) + + if populationStdDev <= 0 { + return math.NaN(), math.NaN(), ErrBounds + } + + se := populationStdDev * math.Sqrt(1.0/float64(n1)+1.0/float64(n2)) + z = (mean1 - mean2) / se + } else { + // One-sample Z-test + if populationStdDev <= 0 { + return math.NaN(), math.NaN(), ErrBounds + } + + se := populationStdDev / math.Sqrt(float64(n1)) + z = (mean1 - populationMean) / se + } + + pvalue = 2 * NormSf(math.Abs(z), 0, 1) + + return z, pvalue, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index f93f686..9e550d2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -55,7 +55,7 @@ github.com/mdlayher/socket # github.com/mdlayher/vsock v1.2.1 ## explicit; go 1.20 github.com/mdlayher/vsock -# github.com/montanaflynn/stats v0.9.0 +# github.com/montanaflynn/stats v0.11.0 ## explicit; go 1.13 github.com/montanaflynn/stats # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822