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) | |
} | |
} |