-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathlinear.js
57 lines (46 loc) · 1.3 KB
/
linear.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { determination } from "./utils/determination";
import { ols } from "./utils/ols";
import { visitPoints } from "./utils/points";
export default function(){
let x = d => d[0],
y = d => d[1],
domain;
function linear(data){
let n = 0,
X = 0, // sum of x
Y = 0, // sum of y
XY = 0, // sum of x * y
X2 = 0, // sum of x * x
xmin = domain ? +domain[0] : Infinity,
xmax = domain ? +domain[1] : -Infinity;
visitPoints(data, x, y, (dx, dy) => {
++n;
X += (dx - X) / n;
Y += (dy - Y) / n;
XY += (dx * dy - XY) / n;
X2 += (dx * dx - X2) / n;
if (!domain){
if (dx < xmin) xmin = dx;
if (dx > xmax) xmax = dx;
}
});
const [intercept, slope] = ols(X, Y, XY, X2),
fn = x => slope * x + intercept,
out = [[xmin, fn(xmin)], [xmax, fn(xmax)]];
out.a = slope;
out.b = intercept;
out.predict = fn;
out.rSquared = determination(data, x, y, Y, fn);
return out;
}
linear.domain = function(arr){
return arguments.length ? (domain = arr, linear) : domain;
}
linear.x = function(fn){
return arguments.length ? (x = fn, linear) : x;
}
linear.y = function(fn){
return arguments.length ? (y = fn, linear) : y;
}
return linear;
}