92 lines
2.6 KiB
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
|
||
|
}
|