The stats package provides basic descriptive statistics functions for statistical analysis. It is designed to offer common, everyday statistical functions that would be explained in a typical high school statistics course.
The package aims to balance performance and accuracy, though some amount of error is inevitable in floating-point computations. The underlying implementations may change, resulting in small changes in their results from version to version. For applications requiring particular guarantees on accuracy, overflow behavior, or version stability, a more specialized statistics implementation should be used.
go get golang.org/x/expimport (
"golang.org/x/exp/stats"
)package main
import (
"fmt"
"golang.org/x/exp/stats"
)
func main() {
// Sample data
values := []float64{1.5, 2.3, 3.1, 4.2, 5.0}
// Calculate mean
mean := stats.Mean(values)
fmt.Printf("Mean: %.2f\n", mean)
// Calculate mean and standard deviation
mean, stdDev := stats.MeanAndStdDev(values)
fmt.Printf("Mean: %.2f, StdDev: %.2f\n", mean, stdDev)
// Calculate median
median := stats.Median(values)
fmt.Printf("Median: %.2f\n", median)
// Calculate quantiles
quantiles := stats.Quantiles(values, 0.25, 0.5, 0.75)
fmt.Printf("25th percentile: %.2f\n", quantiles[0])
fmt.Printf("50th percentile: %.2f\n", quantiles[1])
fmt.Printf("75th percentile: %.2f\n", quantiles[2])
}Computes the arithmetic mean of a dataset.
func Mean[F ~float64](values []F) FDescription: Mean returns the arithmetic mean of the values in the slice. The function does not modify the input array.
Behavior:
Example:
package main
import (
"fmt"
"golang.org/x/exp/stats"
)
func main() {
values := []float64{10, 20, 30, 40, 50}
mean := stats.Mean(values)
fmt.Printf("Mean: %.2f\n", mean) // Output: Mean: 30.00
// Works with any type that underlies float64
floats := []float32{1.5, 2.5, 3.5}
mean32 := stats.Mean(floats)
fmt.Printf("Mean: %.2f\n", mean32) // Output: Mean: 2.50
}Computes both the arithmetic mean and sample standard deviation in a single operation.
func MeanAndStdDev[F ~float64](values []F) (F, F)Description: MeanAndStdDev returns the arithmetic mean and sample standard deviation of the input values. The standard deviation is calculated as the sample standard deviation and is only meaningful when len(values) > 1. The function does not modify the input array.
Behavior:
Example:
package main
import (
"fmt"
"golang.org/x/exp/stats"
)
func main() {
// Student test scores
scores := []float64{85, 90, 78, 92, 88, 76, 95}
mean, stdDev := stats.MeanAndStdDev(scores)
fmt.Printf("Mean Score: %.2f\n", mean) // Mean Score: 86.29
fmt.Printf("Standard Deviation: %.2f\n", stdDev) // Standard Deviation: 6.39
// Single value - standard deviation undefined but still computed
single := []float64{42.0}
mean, stdDev = stats.MeanAndStdDev(single)
fmt.Printf("Mean: %.2f, StdDev: %.2f\n", mean, stdDev)
}Computes the middle value of a sorted dataset.
func Median[F ~float64](values []F) FDescription: Median returns the median of the values in the slice. For odd-length slices, it returns the middle value. For even-length slices, it returns the average of the two middle values. The function does not modify the input array but may perform faster if the slice is already sorted.
Behavior:
Example:
package main
import (
"fmt"
"golang.org/x/exp/stats"
)
func main() {
// Odd number of values
oddValues := []float64{3, 1, 4, 1, 5, 9, 2}
median := stats.Median(oddValues)
fmt.Printf("Median: %.2f\n", median) // Output: Median: 3.00
// Even number of values
evenValues := []float64{10, 20, 30, 40}
median = stats.Median(evenValues)
fmt.Printf("Median: %.2f\n", median) // Output: Median: 25.00
// Already sorted data (faster)
sorted := []float64{1, 2, 3, 4, 5}
median = stats.Median(sorted)
fmt.Printf("Median: %.2f\n", median) // Output: Median: 3.00
}Computes quantiles (percentiles) of a dataset.
func Quantiles[F, Q ~float64](values []F, quantiles ...Q) []FDescription: Quantiles returns a sequence of quantiles of the input values. The returned slice has the same length as the quantiles input slice, with elements corresponding one-to-one to the input quantiles. A quantile of 0 corresponds to the minimum value, and a quantile of 1 corresponds to the maximum value. A quantile of 0.5 is equivalent to the median.
Parameters:
values: The input data slice for which to compute quantilesquantiles: Variable number of quantile values (must be in range [0, 1])Return Value: A slice of floats representing the quantile values, with length equal to the quantiles input
Behavior:
Example:
package main
import (
"fmt"
"golang.org/x/exp/stats"
)
func main() {
// Dataset with 100 values
data := []float64{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
}
// Calculate quartiles (25th, 50th, 75th percentiles)
quartiles := stats.Quantiles(data, 0.25, 0.5, 0.75)
fmt.Printf("25th percentile (Q1): %.2f\n", quartiles[0])
fmt.Printf("50th percentile (Q2/Median): %.2f\n", quartiles[1])
fmt.Printf("75th percentile (Q3): %.2f\n", quartiles[2])
// Calculate deciles
deciles := stats.Quantiles(data, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)
for i, q := range deciles {
fmt.Printf("%.0f%% percentile: %.2f\n", (float64(i)+1)*10, q)
}
// Min and max
minMax := stats.Quantiles(data, 0, 1)
fmt.Printf("Min: %.2f, Max: %.2f\n", minMax[0], minMax[1])
}package main
import (
"fmt"
"golang.org/x/exp/stats"
)
func main() {
// Test scores
scores := []float64{65, 72, 78, 82, 88, 91, 95, 98}
// Get percentile information
q1, median, q3 := stats.Quantiles(scores, 0.25, 0.5, 0.75)
mean, stdDev := stats.MeanAndStdDev(scores)
fmt.Printf("Q1 (25%%): %.1f\n", q1)
fmt.Printf("Median (50%%): %.1f\n", median)
fmt.Printf("Q3 (75%%): %.1f\n", q3)
fmt.Printf("Mean: %.1f ± %.1f\n", mean, stdDev)
fmt.Printf("IQR (Interquartile Range): %.1f\n", q3-q1)
}package main
import (
"fmt"
"golang.org/x/exp/stats"
)
func main() {
// Measurements of a process
measurements := []float64{
9.8, 9.9, 10.0, 10.1, 9.95, 10.05, 9.98, 10.02,
9.99, 10.01, 10.0, 9.97,
}
mean, stdDev := stats.MeanAndStdDev(measurements)
median := stats.Median(measurements)
fmt.Printf("Process Statistics:\n")
fmt.Printf(" Mean: %.3f\n", mean)
fmt.Printf(" Median: %.3f\n", median)
fmt.Printf(" Std Dev: %.4f\n", stdDev)
fmt.Printf(" 95%% CI: [%.3f, %.3f]\n", mean-1.96*stdDev, mean+1.96*stdDev)
}All functions in the stats package use generic type parameters that work with any type that underlies float64. This allows seamless use with custom float types:
package main
import (
"fmt"
"golang.org/x/exp/stats"
)
type Temperature float64 // Custom type
func main() {
temps := []Temperature{98.6, 99.1, 98.9, 100.2, 98.5}
mean := stats.Mean(temps)
fmt.Printf("Mean temperature: %.1f\n", mean)
// Works directly with custom types without conversion
median := stats.Median(temps)
fmt.Printf("Median temperature: %.1f\n", median)
}The stats package handles special floating-point values according to IEEE 754 rules:
Empty Slice Panic: All functions will panic if called with an empty slice
// This will panic
empty := []float64{}
stats.Mean(empty) // panicInvalid Quantile Values: Quantiles must be between 0 and 1
// This will panic
stats.Quantiles(values, 1.5) // panic: quantile outside [0, 1]NaN Propagation: If your data contains NaN, most results will be NaN
values := []float64{1, 2, math.NaN(), 4}
mean := stats.Mean(values) // result: NaNAll functions use the following generic constraints:
// F ~float64 - Any type that underlies float64 (like custom types)
// Q ~float64 - For quantile parameters, any type that underlies float64This allows the functions to work with:
float64 directlytype MyFloat float64The stats package prioritizes correctness and usability over comprehensive statistical features. For applications requiring:
Consider using specialized statistics libraries designed for those specific needs.