Python's matplotlib and seaborn libraries both handle scatter plots well. Matplotlib gives you direct control over marker size, color, opacity, and export settings; seaborn adds DataFrame-aware grouping and regression helpers with less code.
If you do not need a reproducible Python workflow, the free online scatter plot maker is faster for pasting X/Y data, adding a trendline, and exporting an image without writing code.
Method 1: matplotlib
Install and import
If you haven't already, install matplotlib: pip install matplotlib. Then import it in your script or notebook:
import matplotlib.pyplot as plt
Prepare your data
Your X and Y data should be Python lists or NumPy arrays of equal length:
x = [160, 165, 170, 172, 175, 178, 180, 182, 185, 190]
y = [55, 60, 68, 70, 73, 77, 80, 82, 88, 95]
Create the scatter plot
fig, ax = plt.subplots(figsize=(7, 5))
ax.scatter(x, y, color='steelblue', s=60, alpha=0.8, edgecolors='white', linewidths=0.5)
ax.set_xlabel('Height (cm)')
ax.set_ylabel('Weight (kg)')
ax.set_title('Height vs Weight')
plt.tight_layout()
plt.show()
Save as image
fig.savefig('scatter.png', dpi=150, bbox_inches='tight')
# Or SVG for vector output:
fig.savefig('scatter.svg', bbox_inches='tight')
Method 2: seaborn (recommended for statistics)
Seaborn's scatterplot and regplot functions add regression lines and confidence intervals automatically:
Install and import seaborn
pip install seaborn
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
Create a DataFrame
import pandas as pd
df = pd.DataFrame({'height': x, 'weight': y})
Basic scatter with regression line
fig, ax = plt.subplots(figsize=(7, 5))
sns.regplot(data=df, x='height', y='weight', ax=ax,
scatter_kws={'alpha': 0.8, 's': 60},
line_kws={'color': 'tomato'})
ax.set_title('Height vs Weight with Regression Line')
plt.tight_layout()
plt.show()
regplot draws the regression line and a shaded 95% confidence interval automatically.
Color dots by a third variable (group)
df['group'] = ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B']
sns.scatterplot(data=df, x='height', y='weight', hue='group',
palette={'A': 'steelblue', 'B': 'tomato'}, s=80)
plt.tight_layout()
plt.show()
Common customizations
s=parameter — dot size in points² in matplotlib.s=60is a good default; increase to 120 for presentation slides.alpha=— dot transparency (0 = invisible, 1 = solid). Use 0.5–0.7 when dots overlap heavily to show density.edgecolors='white'— thin white border around each dot makes overlapping dots easier to distinguish.hue=(seaborn) — maps a categorical column to dot colors, automatically adding a legend.
Adding correlation coefficient
from scipy import stats
r, p = stats.pearsonr(df['height'], df['weight'])
ax.annotate(f'r = {r:.2f}', xy=(0.05, 0.92), xycoords='axes fraction',
fontsize=10, color='gray')
Use this label as a compact statistical summary, not as proof of causation. If the scatter is curved, clustered, or dominated by one extreme point, show the pattern visually and explain it in the caption.
FAQ
Should I use matplotlib or seaborn for scatter plots?
Seaborn is better when you need regression lines, grouping by color, or pair plots. Matplotlib is better when you need pixel-level control or are building a custom visualization. For quick exploratory analysis, seaborn; for publication-quality custom charts, matplotlib.
How do I prevent overlapping dots in Python scatter plots?
Set alpha=0.3 to make dots semi-transparent — overlapping dots appear darker. For very dense data (thousands of points), use plt.hexbin(x, y) which bins the data into hexagonal cells and shows density with color.
How do I add labels to individual scatter plot points in matplotlib?
labels = ['point1', 'point2', ...]
for i, label in enumerate(labels):
ax.annotate(label, (x[i], y[i]), textcoords='offset points',
xytext=(5, 5), fontsize=8, color='gray')
Only practical for fewer than 15–20 points; more than that becomes unreadable.
References
How this guide is reviewed
This guide is maintained by the ChartsMakers Editorial Team and reviewed for statistical accuracy, product behavior, and clarity. Sources used for factual checks are listed in the References section. See our editorial policy.