summaryrefslogtreecommitdiff
path: root/app/bits/assets/trendline.js
blob: 48e2522eff5ddd7b094316f3aabf2a8a4f2b08ad (plain)
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
function getAvg(arr) {
    const total = arr.reduce((acc, c) => acc + c, 0);
    return total / arr.length;
}

function getSum(arr) {
    return arr.reduce((acc, c) => acc + c, 0);
}

function trendline(data, xKey, yKey) {
    const xData = data.map((value) => value[xKey]);
    const yData = data.map((value) => value[yKey]);

    // average of X values and Y values
    const xMean = getAvg(xData);
    const yMean = getAvg(yData);

    // Subtract X or Y mean from corresponding axis value
    const xMinusxMean = xData.map((val) => val - xMean);
    const yMinusyMean = yData.map((val) => val - yMean);

    const xMinusxMeanSq = xMinusxMean.map((val) => Math.pow(val, 2));

    const xy = [];
    for (let x = 0; x < data.length; x++) {
        xy.push(xMinusxMean[x] * yMinusyMean[x]);
    }

    // const xy = xMinusxMean.map((val, index) => val * yMinusyMean[index]);

    const xySum = getSum(xy);

    // b1 is the slope
    const b1 = xySum / getSum(xMinusxMeanSq);
    // b0 is the start of the slope on the Y axis
    const b0 = yMean - b1 * xMean;

    return {
        slope: b1,
        yStart: b0,
        calcY: (x) => b0 + b1 * x,
    };
}

const averageDelta = ([x,...xs]) => {
    if (x === undefined)
        return NaN
    else
        return xs.reduce(
            ([acc, last], x) => [acc + (x - last), x],
            [0, x]
        ) [0] / xs.length
}