Scatter Plot Best Practices
A good scatter plot shows the relationship between two numeric variables without hiding data behind overlapping points. The three habits that matter most: fix overplotting, add a trend line only when it's honest, and encode any third variable with a channel readers can actually decode.
How Do You Fix Overplotting in a Scatter Plot?
When thousands of points stack on top of each other, use transparency, jitter, sampling, or switch to a density view like hexbin. Pick the lightest fix that makes the density visible.
import matplotlib.pyplot as plt
# 1. Alpha: overlaps darken, revealing density
plt.scatter(x, y, alpha=0.2, s=10)
# 2. Jitter: for discrete values, add small random noise
import numpy as np
plt.scatter(x + np.random.uniform(-0.15, 0.15, len(x)), y, alpha=0.3)
# 3. Sampling: plot a random subset of huge data
idx = np.random.choice(len(x), 5000, replace=False)
plt.scatter(x[idx], y[idx], alpha=0.3)
# 4. Hexbin: bin points into hexagons, color by count
plt.hexbin(x, y, gridsize=40, cmap="Blues")
Rule of thumb: alpha up to ~10k points, hexbin or 2D histograms beyond that.
Should You Add a Trend Line to a Scatter Plot?
Add a trend line when you want readers to see the direction and rough strength of the relationship, but only if the relationship is actually monotonic โ a straight line through a U-shaped cloud is a lie. Plot the points first, then decide.
import seaborn as sns
# Linear fit with confidence band
sns.regplot(x=x, y=y, scatter_kws={"alpha": 0.2})
# Nonlinear pattern? Use LOWESS instead of forcing a line
sns.regplot(x=x, y=y, lowess=True, scatter_kws={"alpha": 0.2})
How Do You Show a Third Variable on a Scatter Plot?
Use color for a categorical third variable (up to ~5-7 groups) and point size for a numeric one โ that's the classic bubble chart. Avoid encoding precise values in size; readers can rank sizes but not read them.
sns.scatterplot(data=df, x="income", y="spend",
hue="segment", # categorical -> color
size="tenure_yrs", # numeric -> point size
alpha=0.5)
If groups overlap heavily, split them into small multiples instead of piling five colors into one panel.
Common Pitfalls
- Default opaque markers: solid points at default size hide 90% of a large dataset. Always shrink and add alpha first.
- Trend line without points: never show only the fitted line โ the scatter is the evidence.
- Correlation from a truncated axis: zooming both axes onto the cloud exaggerates the visual slope; note the ranges.
- Too many hue groups: beyond ~7 colors nobody can match points to the legend. Facet instead.
- Jittering continuous data: jitter is for discrete/rounded values only; on continuous data it just adds error.
Pro Tip: Before styling anything, plot plt.scatter(x, y, s=2, alpha=0.1). Ten seconds of tiny transparent dots tells you whether you need jitter, hexbin, or nothing at all.