UNPKG

locutus

Version:

Locutus other languages' standard libraries to JavaScript for fun and educational purposes

51 lines (50 loc) 2.32 kB
import { assertStatisticsArray, statisticsMeanFromSequence, sumProducts, toStatisticNumber, } from "../_helpers/_statistics.js"; export function linear_regression(x, y, proportional = false) { // discuss at: https://locutus.io/python/statistics/linear_regression/ // parity verified: Python 3.12 // original by: Kevin van Zonneveld (https://kvz.io) // note 1: Returns ordinary least-squares slope and intercept, mirroring Python's named tuple as a plain object. // example 1: linear_regression([1, 2, 3], [2, 4, 6]) // returns 1: {slope: 2, intercept: 0} // example 2: linear_regression([1, 2, 3], [1, 2, 2]) // returns 2: {slope: 0.5, intercept: 0.6666666666666667} // example 3: linear_regression([1, 2, 3], [2, 4, 6], true) // returns 3: {slope: 2, intercept: 0} const xValues = assertStatisticsArray(x, 'linear_regression').map((value) => toStatisticNumber(value, 'linear_regression')); const yValues = assertStatisticsArray(y, 'linear_regression').map((value) => toStatisticNumber(value, 'linear_regression')); const n = xValues.length; if (yValues.length !== n) { throw new Error('linear regression requires that both inputs have same number of data points'); } if (n < 2) { throw new Error('linear regression requires at least two data points'); } if (proportional) { const sxy = sumProducts(xValues, yValues) + 0; const sxx = sumProducts(xValues, xValues); if (sxx === 0) { throw new Error('x is constant'); } return { slope: sxy / sxx, intercept: 0 }; } const xbar = statisticsMeanFromSequence({ values: xValues, integral: xValues.every(Number.isInteger), }); const ybar = statisticsMeanFromSequence({ values: yValues, integral: yValues.every(Number.isInteger), }); const centeredX = xValues.map((value) => value - xbar); const centeredY = yValues.map((value) => value - ybar); const sxy = sumProducts(centeredX, centeredY) + 0; const sxx = sumProducts(centeredX, centeredX); if (sxx === 0) { throw new Error('x is constant'); } const slope = sxy / sxx; return { slope, intercept: ybar - slope * xbar, }; }