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 }