Draw the single best straight line through a cloud of data points — that line is your prediction machine.
Save
Complete lesson & earn 250 PX
EXERCISE
1Linear regression finds the single best straight line through a cloud of scattered data points — turning chaos into a prediction machine.
Save
EXERCISE
2One function call gives you everything — slope, intercept, r-value, p-value, and standard error. Here is what each one means.
Save
EXERCISE
3A regression line on a scatter plot turns abstract numbers into a visual story you can instantly understand.
Save
Imagine throwing a handful of rice onto a table. The grains scatter, but you can still lay a ruler through them in a way that best represents the overall direction. is that ruler — it finds the line that minimises the total distance from every point to the line.
The core idea:
Data points rarely sit perfectly on a line. Linear regression finds the line that is the least wrong across all points.
import matplotlib.pyplot as plt
from scipy import stats
x = [5, 7, 8, 7, 2, 17, 2, 9, 4, 11, 12, 9, 6]
y = [99, 86, 87, 88, 111, 86, 103, 87, 94, 78, 77, 85, 86]
slope, intercept, r, p, std_err = stats.linregress(x, y)
print(f"Slope: {round(slope, 2)}")
# Output: Slope: -1.75
print(f"Intercept: {round(intercept, 2)}")
# Output: Intercept: 103.1
What slope and intercept mean:
| Term | Meaning | In this example |
|---|---|---|
| Slope | How much y changes when x goes up by 1 | -1.75 (speed drops ~1.75 for each year older) |
| Intercept | The y value when x is 0 | 103.1 (a brand-new car would go ~103 km/h) |
> 💡 Key Insight: The equation of the line is y = slope × x + intercept. This one formula is your machine — plug in any x value and get a predicted y. That is the entire point of regression: turning a pattern in past data into a formula for the future.
Think of linregress() as a Swiss Army knife for linear relationships. You hand it two arrays, and it hands back five numbers that tell the complete story of the relationship.
The five return values:
from scipy import stats
x = [5, 7, 8, 7, 2, 17, 2, 9, 4, 11, 12, 9, 6]
y = [99, 86, 87, 88, 111, 86, 103, 87, 94, 78, 77, 85, 86]
slope, intercept, r, p, std_err = stats.linregress(x, y)
print(f"Slope: {round(slope, 4)}")
# Output: Slope: -1.7512
print(f"Intercept: {round(intercept, 4)}")
# Output: Intercept: 103.1045
print(f"R-value: {round(r, 4)}")
# Output: R-value: -0.7586
print(f"P-value: {round(p, 4)}")
# Output: P-value: 0.0027
print(f"Std Error: {round(std_err, 4)}")
# Output: Std Error: 0.4553
| Value | What It Tells You |
|---|---|
slope | Direction and steepness of the line |
intercept | Where the line crosses the y-axis |
r | Strength of the relationship (-1 to 1) |
p | Statistical significance (< 0.05 = significant) |
std_err | Uncertainty in the slope estimate |
Building the prediction function:
def predict(x_value):
return slope * x_value + intercept
print(f"Predicted speed for 10-year car: {round(predict(10), 2)}")
# Output: Predicted speed for 10-year car: 85.59
> 💡 Key Insight: The p-value tells you whether the relationship is real or just a coincidence. A p-value below 0.05 means there is less than a 5% chance this relationship happened by random luck. In our car example, p=0.0027 — very strong evidence that age really does affect speed.
A scatter plot shows what happened. Adding a regression line shows the trend — and where you expect future data points to land.
Drawing the line through the dots:
import matplotlib.pyplot as plt
from scipy import stats
x = [5, 7, 8, 7, 2, 17, 2, 9, 4, 11, 12, 9, 6]
y = [99, 86, 87, 88, 111, 86, 103, 87, 94, 78, 77, 85, 86]
slope, intercept, r, p, std_err = stats.linregress(x, y)
def myfunc(x):
return slope * x + intercept
mymodel = list(map(myfunc, x))
plt.scatter(x, y)
plt.plot(x, mymodel, color="red")
plt.xlabel("Car Age (years)")
plt.ylabel("Speed (km/h)")
plt.title(f"Linear Regression (r={round(r, 2)})")
plt.show()
# Output: Scatter plot with a red downward-sloping line
Reading the result:
# The distance from each dot to the line = the "error"
errors = [y[i] - myfunc(x[i]) for i in range(len(x))]
print([round(e, 1) for e in errors])
# Output: [4.6, -4.8, -2.1, -2.8, 11.4, -12.3, 3.4, -0.4, -2.1, -5.8, -5.1, -2.4, 2.4]
> 💡 Key Insight: The regression line minimises the sum of squared errors — that is why it is called "least squares regression." It does not try to pass through any single point; it finds the line that is collectively closest to ALL points. Some dots will be above, some below — balance is the goal.
Linear regression finds the straight line that best fits your data. Use SciPy's linregress() to compute slope and intercept.