Skip to content

Instantly share code, notes, and snippets.

@brentp
Created September 21, 2016 15:07
Show Gist options
  • Save brentp/7b27093195f621677f2b0ae6f66397cb to your computer and use it in GitHub Desktop.
Save brentp/7b27093195f621677f2b0ae6f66397cb to your computer and use it in GitHub Desktop.

usage

cat example-data.txt | go run hist.go -c 1 -g 2 -b 30

0.53 a
-1.47 a
0.02 a
-0.01 a
-1.20 a
1.10 a
0.34 a
-1.27 a
-0.82 a
1.48 a
0.55 a
0.62 a
0.88 a
0.67 a
-0.99 a
-0.54 a
0.75 a
1.07 a
-0.11 a
0.67 a
0.88 a
0.42 a
-0.09 a
1.96 a
-0.22 a
-0.82 a
0.25 a
-0.84 a
0.70 a
-1.01 a
0.37 a
0.84 a
-0.19 a
1.09 a
0.94 a
-0.80 a
1.05 a
0.52 a
0.10 a
-0.35 a
1.81 a
-0.54 a
-0.69 a
1.01 a
0.46 a
-0.48 a
-1.36 a
2.43 a
-0.01 a
0.38 a
-0.77 a
0.17 a
-1.09 a
-0.47 a
-2.40 a
-1.30 a
1.38 a
0.80 a
0.91 a
0.18 a
1.93 a
0.67 a
-0.51 a
0.27 a
-2.40 a
-1.86 a
-0.37 a
-0.74 a
0.12 a
0.53 a
-1.63 a
0.13 a
-0.17 a
2.76 a
-0.74 a
0.92 a
1.68 a
0.96 a
0.01 a
0.45 a
0.41 a
-0.46 a
-0.39 a
-0.93 a
2.07 a
0.77 a
1.81 a
-0.26 a
0.29 a
0.45 a
0.82 a
-0.61 a
0.19 a
1.27 a
-2.13 a
-0.83 a
0.69 a
-1.03 a
-1.79 a
-0.75 a
-0.87 a
1.46 a
-0.27 a
-0.79 a
-0.16 a
0.53 a
-0.25 a
0.30 a
-0.30 a
1.38 a
0.36 a
-1.55 a
0.81 a
-1.68 a
-0.69 a
0.66 a
-0.65 a
-1.13 a
-0.79 a
0.80 a
-0.26 a
-0.34 a
0.16 a
-0.18 a
-1.42 a
0.38 a
0.14 a
-0.29 a
-0.67 a
0.13 a
1.15 a
-1.13 a
-1.54 a
0.42 a
-0.44 a
0.10 a
-0.20 a
-1.54 a
0.92 a
0.28 a
-1.14 a
1.07 a
-0.82 a
-1.25 a
0.49 a
-0.22 a
-0.55 a
0.39 a
0.32 a
0.05 a
1.41 a
0.04 a
0.81 a
-0.55 a
-1.79 a
0.77 a
0.18 a
-0.50 a
-0.49 a
1.25 a
-0.09 a
1.13 a
2.05 a
-1.35 a
0.06 a
-0.86 a
-2.27 a
1.74 a
1.39 a
-0.16 a
1.55 a
1.22 a
-0.20 a
-1.00 a
2.06 a
1.52 a
0.18 a
0.24 a
-0.70 a
1.86 a
-0.67 a
2.12 a
-0.51 a
-0.85 a
0.64 a
-0.72 a
-1.13 a
1.20 a
-1.74 a
0.93 a
-0.33 a
1.36 a
-1.29 a
0.04 a
1.59 a
0.89 a
-0.87 a
-0.82 a
-0.98 a
1.42 a
-0.05 b
0.19 b
0.18 b
0.78 b
-1.14 b
-0.45 b
-0.74 b
-0.95 b
-0.72 b
2.22 b
-0.58 b
-2.37 b
-0.86 b
1.55 b
-0.12 b
1.10 b
-1.69 b
1.65 b
0.53 b
0.81 b
0.57 b
-0.98 b
0.88 b
2.62 b
0.56 b
-1.15 b
-0.43 b
0.48 b
1.59 b
-0.96 b
0.13 b
0.50 b
-1.89 b
-0.24 b
0.08 b
0.58 b
-0.67 b
-0.70 b
-1.59 b
0.22 b
-0.05 b
1.62 b
-1.05 b
2.11 b
-1.10 b
0.10 b
-0.81 b
-0.72 b
0.43 b
0.00 b
1.69 b
-0.69 b
0.05 b
-0.51 b
0.78 b
1.47 b
0.20 b
1.83 b
-0.23 b
-0.27 b
0.43 b
-0.47 b
0.83 b
0.41 b
1.60 b
-0.56 b
0.23 b
0.73 b
-1.08 b
0.44 b
1.22 b
1.91 b
1.01 b
1.49 b
-2.05 b
0.78 b
1.09 b
1.61 b
-0.29 b
-0.75 b
-0.58 b
-0.60 b
2.18 b
1.47 b
0.01 b
0.92 b
0.90 b
-0.55 b
-0.89 b
-0.68 b
0.23 b
-0.90 b
0.79 b
-1.28 b
0.02 b
-1.48 b
-0.05 b
-1.16 b
-0.89 b
2.11 b
-1.59 b
-1.09 b
-1.55 b
-0.17 b
0.21 b
-0.01 b
0.53 b
-0.30 b
0.96 b
0.56 b
0.59 b
0.16 b
-0.83 b
1.86 b
0.98 b
-0.29 b
2.47 b
1.12 b
3.14 b
0.06 b
-0.79 b
-0.28 b
0.21 b
-1.04 b
2.16 b
-0.50 b
1.48 b
-0.13 b
-0.69 b
-0.46 b
0.09 b
0.42 b
-0.97 b
-0.61 b
-0.91 b
0.70 b
-0.52 b
2.02 b
-1.24 b
0.69 b
0.60 b
0.33 b
-0.14 b
-0.48 b
1.70 b
-0.87 b
0.82 b
0.16 b
-0.20 b
0.60 b
0.72 b
-0.05 b
-0.39 b
-0.39 b
0.26 b
-0.71 b
1.07 b
-0.47 b
1.68 b
1.12 b
1.24 b
1.11 b
-0.85 b
0.36 b
0.71 b
0.03 b
-0.28 b
-1.59 b
-0.82 b
0.05 b
-0.60 b
-0.27 b
-0.51 b
1.67 b
-0.26 b
-1.17 b
0.15 b
1.17 b
-0.10 b
-0.92 b
1.01 b
-0.35 b
-2.56 b
0.51 b
-0.14 b
-0.21 b
1.06 b
-0.08 b
-0.87 b
0.90 b
-0.41 b
-1.65 b
0.81 b
-0.21 b
0.21 b
0.13 b
0.24 b
0.75 b
-1.89 b
0.30 b
0.98 c
0.40 c
0.56 c
0.43 c
0.01 c
0.59 c
0.28 c
0.13 c
0.31 c
0.20 c
0.18 c
0.29 c
0.46 c
0.09 c
0.26 c
0.08 c
1.00 c
0.81 c
0.78 c
0.09 c
0.87 c
0.87 c
0.50 c
0.65 c
0.24 c
0.59 c
0.55 c
0.92 c
0.38 c
0.08 c
0.14 c
0.62 c
0.14 c
0.01 c
0.55 c
0.70 c
0.88 c
0.02 c
0.70 c
0.41 c
0.38 c
0.71 c
0.56 c
0.38 c
0.57 c
0.03 c
0.44 c
0.25 c
0.68 c
0.84 c
0.37 c
0.66 c
0.66 c
0.29 c
0.59 c
0.81 c
0.98 c
0.52 c
0.30 c
0.54 c
0.04 c
0.55 c
0.94 c
0.07 c
1.00 c
0.27 c
0.34 c
0.19 c
0.22 c
0.52 c
0.81 c
0.01 c
0.73 c
0.74 c
0.16 c
0.66 c
0.05 c
0.95 c
0.54 c
0.21 c
0.99 c
0.11 c
0.44 c
0.49 c
0.26 c
0.25 c
0.00 c
0.04 c
0.05 c
0.68 c
0.40 c
0.12 c
0.85 c
0.50 c
0.47 c
0.33 c
0.95 c
0.50 c
0.08 c
0.99 c
0.51 c
0.14 c
0.39 c
0.13 c
1.00 c
0.75 c
0.79 c
0.57 c
0.72 c
0.50 c
0.55 c
0.37 c
0.45 c
0.64 c
0.91 c
0.92 c
0.91 c
0.63 c
0.49 c
0.74 c
0.50 c
0.50 c
0.50 c
0.01 c
0.09 c
0.10 c
0.21 c
0.38 c
0.22 c
0.72 c
0.87 c
0.48 c
0.43 c
0.90 c
0.29 c
0.95 c
0.53 c
0.27 c
0.89 c
0.22 c
0.11 c
0.55 c
0.31 c
0.17 c
0.86 c
0.12 c
0.37 c
0.87 c
0.40 c
0.46 c
0.10 c
0.92 c
0.72 c
0.83 c
0.48 c
0.68 c
0.27 c
0.78 c
0.45 c
0.24 c
0.74 c
0.29 c
0.86 c
0.83 c
0.79 c
0.02 c
0.97 c
0.85 c
0.03 c
0.24 c
0.52 c
0.10 c
0.25 c
0.04 c
0.01 c
0.87 c
0.04 c
0.77 c
0.21 c
0.48 c
0.73 c
0.20 c
0.06 c
0.27 c
0.01 c
0.06 c
0.17 c
0.88 c
0.92 c
0.53 c
0.90 c
0.02 c
0.88 c
0.68 c
0.52 c
0.88 c
0.80 c
0.72 c
0.59 c
0.49 c
package main
import (
"bufio"
"fmt"
"log"
"os"
"regexp"
"sort"
"strconv"
arg "github.com/alexflint/go-arg"
"github.com/gonum/plot"
"github.com/gonum/plot/plotter"
"github.com/gonum/plot/plotutil"
"github.com/gonum/plot/vg"
)
type dargs struct {
Col int `arg:"-c,required,help:1-based column number to use for histogram"`
Group int `arg:"-g,help:optional 1-based column number to use grouping"`
Sep string `arg:"-s,help:optional sep for columns default is '\t'"`
Bins int `arg:"-b,help:optional number of bins."`
Path string `arg:"-p,help:optional path to save plot."`
}
func pcheck(e error) {
if e != nil {
panic(e)
}
}
func MustAtof(s string) float64 {
v, err := strconv.ParseFloat(s, 64)
pcheck(err)
return v
}
// Main is run from the dispatcher
func main() {
args := dargs{Sep: "\t", Bins: 20, Path: "hist.png"}
arg.MustParse(&args)
args.Group--
args.Col--
run(args)
}
func read(args dargs) map[string][]float64 {
sep := regexp.MustCompile(args.Sep)
scanner := bufio.NewScanner(os.Stdin)
scanner.Buffer(make([]byte, 0, 16384), 5e9)
grouped := make(map[string][]float64)
nErr := 0
for scanner.Scan() {
line := scanner.Text()
toks := sep.Split(line, -1)
v, err := strconv.ParseFloat(toks[args.Col], 64)
if err != nil {
if nErr < 5 {
log.Println(err)
}
nErr++
continue
}
var g string
if args.Group > -1 {
g = toks[args.Group]
} else {
g = "default"
}
if _, ok := grouped[g]; !ok {
grouped[g] = make([]float64, 0, 256)
}
grouped[g] = append(grouped[g], v)
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
return grouped
}
func mapkeys(m map[string][]float64) []string {
var ks []string
for k := range m {
ks = append(ks, k)
}
sort.Strings(ks)
return ks
}
func run(args dargs) {
grouped := read(args)
keys := mapkeys(grouped)
p, err := plot.New()
if err != nil {
panic(err)
}
p.Y.Label.Text = "Count"
w := float64(30/len(grouped)) * float64(20) / float64(args.Bins)
var bars []plot.Plotter
for i, k := range keys {
tmp, err := plotter.NewHist(plotter.Values(grouped[k]), args.Bins)
pcheck(err)
vals := make([]float64, len(tmp.Bins))
for i, b := range tmp.Bins {
vals[i] = b.Weight
}
bar, err := plotter.NewBarChart(plotter.Values(vals), vg.Points(w+0.01))
pcheck(err)
bar.LineStyle.Width = vg.Length(0.1)
bar.Color = plotutil.Color(i)
bar.Offset = vg.Points(float64(i) * w)
p.Legend.Add(k, bar)
//p.Add(bar)
bars = append(bars, bar)
}
p.Add(bars...)
log.Println(p.X.Min, p.X.Max)
p.Legend.Top = true
if err := p.Save(10*vg.Inch, 3*vg.Inch, args.Path); err != nil {
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment