JavaScript · Course navigation

JavaScript: fitting a line with least squares

Compute the slope, intercept, and R² of the best-fit line in closed form.

On this page
Before you start

JavaScript arrays, reduce, and the mean.

  • Compute the slope, intercept, and R² of the best-fit line in closed form.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

Simple linear regression finds the line y = m·x + b that minimizes the sum of squared vertical errors. For one input variable there is a closed-form solution: the slope is the covariance of x and y divided by the variance of x, and the intercept makes the line pass through the point of means.

R² measures how much of the variation in y the line explains. It is 1 minus the ratio of the residual sum of squares to the total sum of squares, and it is 1 for a perfect fit and near 0 for a useless one. The data here are roughly y = 2x with a little noise, so the slope should be close to 2.

Code example

JavaScript
const x = [1, 2, 3, 4, 5];
const y = [2.2, 4.1, 6.2, 7.9, 10.1];

const mean = (values) => values.reduce((a, b) => a + b, 0) / values.length;
const mx = mean(x);
const my = mean(y);

let sxy = 0;
let sxx = 0;
for (let i = 0; i < x.length; i++) {
  sxy += (x[i] - mx) * (y[i] - my);
  sxx += (x[i] - mx) ** 2;
}
const slope = sxy / sxx;
const intercept = my - slope * mx;

let residual = 0;
let total = 0;
for (let i = 0; i < x.length; i++) {
  residual += (y[i] - (slope * x[i] + intercept)) ** 2;
  total += (y[i] - my) ** 2;
}

console.log("slope " + slope.toFixed(3) + ", intercept " + intercept.toFixed(3));
console.log("R squared " + (1 - residual / total).toFixed(4));
console.log("prediction for x=6: " + (slope * 6 + intercept).toFixed(2));
Output
slope 1.960, intercept 0.220
R squared 0.9989
prediction for x=6: 11.98

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1const x = [1, 2, 3, 4, 5];
2const y = [2.2, 4.1, 6.2, 7.9, 10.1];
3
4const mean = (values) => values.reduce((a, b) => a + b, 0) / values.length;
5const mx = mean(x);
6const my = mean(y);
7
8let sxy = 0;
9let sxx = 0;
10for (let i = 0; i < x.length; i++) {
11 sxy += (x[i] - mx) * (y[i] - my);
12 sxx += (x[i] - mx) ** 2;
13}
14const slope = sxy / sxx;
15const intercept = my - slope * mx;
16
17let residual = 0;
18let total = 0;
19for (let i = 0; i < x.length; i++) {
20 residual += (y[i] - (slope * x[i] + intercept)) ** 2;
21 total += (y[i] - my) ** 2;
22}
23
24console.log("slope " + slope.toFixed(3) + ", intercept " + intercept.toFixed(3));
25console.log("R squared " + (1 - residual / total).toFixed(4));
26console.log("prediction for x=6: " + (slope * 6 + intercept).toFixed(2));

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Covariance divided by variance: 19.6 / 10 = 1.96.slope = 1.96
—
The line passes through the means (3, 6.1): 6.1 − 1.96·3 = 0.22.intercept = 0.22
—
The fitted line is close to y = 2x.intercept = 0.22
slope 1.960, intercept 0.220
Almost all of the variation is explained by the line.intercept = 0.22
slope 1.960, intercept 0.220
R squared 0.9989
1.96·6 + 0.22.intercept = 0.22
slope 1.960, intercept 0.220
R squared 0.9989
prediction for x=6: 11.98

Behind the scenes

How JavaScript processes this code

A JavaScript engine parses and runs the source. A function body runs when the function is called. console.log writes to the console.

Cost and common mistakes

O(n) time and O(1) extra space.

  • A high R² does not prove that the relationship is causal, or that the model will predict well outside the observed range.
  • Least squares is sensitive to outliers, because errors are squared.
  • toFixed returns a string and rounds for display only. Keep full precision for calculation.

Try it yourself

What does the model predict for x = 0?

Reveal answer and reasoning

The intercept, which is 0.22.

Further reading