route/vendor/github.com/aclements/go-moremath/cmd/dist/dist.go

92 lines
2.6 KiB
Go

// dist reads newline-separated numbers and describes their distribution.
//
// For example,
//
// $ seq 1 20 | grep -v 1 | dist
// N 9 sum 64 mean 7.11111 gmean 5.78509 std dev 5.34894 variance 28.6111
//
// min 2
// 1%ile 2
// 5%ile 2
// 25%ile 3.66667
// median 6
// 75%ile 8.33333
// 95%ile 20
// 99%ile 20
// max 20
//
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣠⠖⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠦⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡖ 0.1
// ⠀⠀⠀⠀⠀⠀⠀⢀⣠⠴⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠲⢤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇
// ⠠⠤⠤⠤⠤⠴⠒⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠑⠲⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠴⠒⠋⠉⠉⠀⠀⠉⠉⠙⠒⠦⠤⠤⠤⠤⠄⠧ 0.0
// ⠈⠉⠉⠉⠉⠙⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠋⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠋⠉⠉⠉⠉⠉⠉⠉⠉⠉⠁
// 0 10 20
package main
import (
"bufio"
"fmt"
"io"
"math"
"os"
"strconv"
"strings"
"github.com/aclements/go-moremath/stats"
)
func main() {
s := readInput(os.Stdin)
if len(s.Xs) == 0 {
fmt.Fprintln(os.Stderr, "no input")
return
}
s.Sort()
fmt.Printf("N %d sum %.6g mean %.6g", len(s.Xs), s.Sum(), s.Mean())
gmean := s.GeoMean()
if !math.IsNaN(gmean) {
fmt.Printf(" gmean %.6g", gmean)
}
fmt.Printf(" std dev %.6g variance %.6g\n", s.StdDev(), s.Variance())
fmt.Println()
// Quartiles and tails.
labels := map[int]string{0: "min", 50: "median", 100: "max"}
for _, p := range []int{0, 1, 5, 25, 50, 75, 95, 99, 100} {
label, ok := labels[p]
if !ok {
label = fmt.Sprintf("%d%%ile", p)
}
fmt.Printf("%8s %.6g\n", label, s.Quantile(float64(p)/100))
}
fmt.Println()
// Kernel density estimate.
kde := &stats.KDE{Sample: s}
FprintPDF(os.Stdout, kde)
}
func readInput(r io.Reader) (sample stats.Sample) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
l := scanner.Text()
l = strings.TrimSpace(l)
if l == "" {
continue
}
value, err := strconv.ParseFloat(l, 64)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
sample.Xs = append(sample.Xs, value)
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
return
}