Very simple linear regression
curl -s //www.lauradhamilton.com/data_files/cricket_chirps_versus_temperature.txt | go run main.go > output.svg
2018/06/13 19:57:59 3.3057614388773593*x+24.966014428303183
| package main | |
| import ( | |
| "encoding/csv" | |
| "log" | |
| "os" | |
| "strconv" | |
| "gonum.org/v1/gonum/stat" | |
| "gonum.org/v1/plot" | |
| "gonum.org/v1/plot/plotter" | |
| "gonum.org/v1/plot/vg" | |
| ) | |
| type xy struct { | |
| x []float64 | |
| y []float64 | |
| } | |
| func (d xy) Len() int { | |
| return len(d.x) | |
| } | |
| func (d xy) XY(i int) (x, y float64) { | |
| x = d.x[i] | |
| y = d.y[i] | |
| return | |
| } | |
| func main() { | |
| r := csv.NewReader(os.Stdin) | |
| records, err := r.ReadAll() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| size := len(records) | |
| data := xy{ | |
| x: make([]float64, size), | |
| y: make([]float64, size), | |
| } | |
| for i, v := range records { | |
| if len(v) != 2 { | |
| log.Fatal("Expected two elements") | |
| } | |
| if s, err := strconv.ParseFloat(v[0], 64); err == nil { | |
| data.y[i] = s | |
| } | |
| if s, err := strconv.ParseFloat(v[1], 64); err == nil { | |
| data.x[i] = s | |
| } | |
| } | |
| b, a := stat.LinearRegression(data.x, data.y, nil, false) | |
| log.Printf("%v*x+%v", a, b) | |
| line := plotter.NewFunction(func(x float64) float64 { return a*x + b }) | |
| p, err := plot.New() | |
| if err != nil { | |
| log.Panic(err) | |
| } | |
| plotter.DefaultLineStyle.Width = vg.Points(1) | |
| plotter.DefaultGlyphStyle.Radius = vg.Points(2) | |
| scatter, err := plotter.NewScatter(data) | |
| if err != nil { | |
| log.Panic(err) | |
| } | |
| p.Add(scatter, line) | |
| w, err := p.WriterTo(300, 300, "svg") | |
| if err != nil { | |
| log.Panic(err) | |
| } | |
| _, err = w.WriteTo(os.Stdout) | |
| if err != nil { | |
| log.Panic(err) | |
| } | |
| } |