A Seaborn scatter plot shows how two numeric variables relate: each point is one observation, with position on the x- and y-axes. The main function is sns.scatterplot(). Use it when you want a clean Matplotlib-based scatter chart that works directly with Pandas DataFrames and optional group styling with hue, style, and size.
Install if needed: pip install seaborn pandas matplotlib. Examples below use Seaborn’s built-in tips dataset and save figures with savefig() so scripts run headless.
Tested on: Python 3.13.3; seaborn 0.13.2; kernel 6.14.0-37-generic.
Seaborn scatter plot quick reference
| Task | Use |
|---|---|
| Basic scatter plot | sns.scatterplot(data=df, x="x_col", y="y_col") |
| Color points by group | hue="group_col" |
| Change marker style by group | style="group_col" |
| Change point size by variable | size="value_col" |
| Use a color palette | palette="deep" or palette="viridis" |
| Make points transparent | alpha=0.5 |
| Change marker size | s=80 |
| Add title and labels | ax.set_title(), ax.set_xlabel(), ax.set_ylabel() |
| Move or edit legend | ax.legend() or plt.legend() |
| Add regression line | sns.regplot() |
| Create multiple scatter plots by category | sns.relplot(kind="scatter", col="category") |
Basic sns.scatterplot() syntax
sns.scatterplot(data=df, x="column_name", y="column_name")data— usually a Pandas DataFrame (long-form: one row per observation).x,y— column names as strings, or array-like values if you omitdata.- Return value — a Matplotlib
Axesobject (when plotting on an existing figure) that you can customize further.
Seaborn builds on Matplotlib: titles, labels, figure size, and grids use standard Axes or pyplot calls after plotting.
Create a basic Seaborn scatter plot
import matplotlib.pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(data=tips, x="total_bill", y="tip", ax=ax)
ax.set_title("Tip vs total bill")
ax.set_xlabel("Total bill ($)")
ax.set_ylabel("Tip ($)")
fig.savefig("scatter_basic.png", bbox_inches="tight")
plt.show()You should see points for total_bill vs tip—244 rows in the sample dataset. In a script, call plt.show() only when you want an interactive window; use savefig() for files.
Add color groups with hue
hue colors markers by a column—best for comparing the same x–y relationship across groups (category or numeric; Seaborn scales color differently for each).
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(data=tips, x="total_bill", y="tip", hue="day", ax=ax)
ax.set_title("Tip vs bill by day")
fig.savefig("scatter_hue.png", bbox_inches="tight")Use hue when group comparison matters, not only for decoration. A legend is added automatically.
Change marker style with style
style maps a column to marker shapes—useful when color alone is not enough (print, accessibility, or black-and-white output).
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(
data=tips,
x="total_bill",
y="tip",
hue="day",
style="smoker",
ax=ax,
)
fig.savefig("scatter_style.png", bbox_inches="tight")The Seaborn relational plot guide notes that repeating the same variable in hue and style can improve accessibility when chosen deliberately—not by accident with unrelated columns.
Change point size with size
size maps a third numeric variable to marker area—bubble-style scatter plots. Control the range with sizes=(min, max):
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(
data=tips,
x="total_bill",
y="tip",
hue="day",
size="size",
sizes=(40, 200),
ax=ax,
)
fig.savefig("scatter_size.png", bbox_inches="tight")Do not stack hue, style, and size on unrelated columns unless the chart stays readable. Too many semantic mappings make plots hard to interpret—Seaborn’s own tutorial warns about this.
Customize colors, palette, markers, and transparency
| Parameter | Purpose |
|---|---|
color |
Single color for all points (no grouping) |
hue + palette |
Group colors ("deep", "viridis", "Set2", etc.) |
alpha |
Transparency (0–1); helps overlapping points |
s |
Fixed marker size when not using size= mapping |
edgecolor, linewidth |
Marker border color and width |
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(
data=tips,
x="total_bill",
y="tip",
hue="time",
palette="viridis",
alpha=0.7,
s=60,
edgecolor="white",
linewidth=0.5,
ax=ax,
)
fig.savefig("scatter_custom.png", bbox_inches="tight")palette without hue does not create group colors—pair them when you need categories.
Add title, axis labels, grid, and figure size
Set figure size before plotting when you create the figure yourself:
fig, ax = plt.subplots(figsize=(10, 6))
sns.scatterplot(data=tips, x="total_bill", y="tip", hue="day", ax=ax)
ax.set_title("Restaurant tips")
ax.set_xlabel("Total bill ($)")
ax.set_ylabel("Tip ($)")
ax.grid(True, alpha=0.3)
fig.savefig("scatter_labels.png", bbox_inches="tight")Prefer ax.set_* on the Axes returned by scatterplot() so you target the correct subplot.
Control legend in Seaborn scatter plot
Legends appear automatically when you use hue, style, or size. Hide or move them when they cover data:
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(data=tips, x="total_bill", y="tip", hue="day", ax=ax)
ax.legend(title="Day", bbox_to_anchor=(1.02, 1), loc="upper left")
fig.savefig("scatter_legend.png", bbox_inches="tight")Use legend=False on scatterplot() to suppress the legend. For fine control, grab ax.get_legend() or call ax.legend(...) with bbox_to_anchor to place the legend outside the plot area.
Add regression line to a Seaborn scatter plot
sns.scatterplot() does not fit a trend line. Options:
Option 1 — regplot() (scatter + line in one call):
fig, ax = plt.subplots(figsize=(8, 5))
sns.regplot(data=tips, x="total_bill", y="tip", ax=ax)
fig.savefig("regplot_basic.png", bbox_inches="tight")Option 2 — custom scatter styling + line:
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(data=tips, x="total_bill", y="tip", alpha=0.5, ax=ax)
sns.regplot(data=tips, x="total_bill", y="tip", scatter=False, ax=ax)
fig.savefig("scatter_plus_line.png", bbox_inches="tight")regplot(scatter=False) draws only the regression line on the same Axes.
Create multiple scatter plots with relplot()
For figure-level faceting, use sns.relplot(kind="scatter") with col= or row=:
import seaborn as sns
tips = sns.load_dataset("tips")
g = sns.relplot(
data=tips,
kind="scatter",
x="total_bill",
y="tip",
hue="smoker",
col="time",
height=4,
aspect=1.1,
)
g.savefig("relplot_scatter.png", bbox_inches="tight")relplot() wraps scatterplot() with a FacetGrid and keeps semantic mappings consistent across facets—safer than wiring FacetGrid manually for simple split charts.
Handle overplotting in scatter plots
When many points overlap, the chart looks like a solid blob.
- Lower
alpha(for example0.3–0.6). - Reduce marker size with
sor smallersizesin asizemapping. - Sample very large datasets before plotting.
- For dense numeric clouds, consider
sns.kdeplot(),plt.hexbin(),sns.jointplot(), orhistplotinstead of a raw scatter. - For discrete categories on one axis,
stripplot()orswarmplot()may read better than a scatter.
Seaborn scatterplot vs regplot vs relplot vs pairplot
| Function | Use when |
|---|---|
sns.scatterplot() |
One scatter plot on one Axes |
sns.regplot() |
Scatter with a regression line |
sns.relplot(kind="scatter") |
Same scatter mapping split into rows/columns |
sns.pairplot() |
Scatter matrix for many numeric column pairs |
Mistakes to avoid
- Passing
x="col"andy="col"withoutdata=df(or pass Series/arrays directly). - Mapping
hue,style, andsizeon three unrelated columns—chart becomes unreadable. - Expecting
scatterplot()to draw a regression line—useregplot(). - Putting categorical data on both axes when a bar or strip plot would be clearer.
- Forgetting
plt.show()in local scripts (not needed forsavefig()-only workflows). - Plotting hundreds of thousands of points with full opacity and large markers.
- Setting
palettewithouthueand expecting grouped colors. - Confusing
sns.scatterplot()withplt.scatter()—the Seaborn API is DataFrame-oriented and semantic mappings differ.
Summary
Use sns.scatterplot() for Seaborn scatter plots: x and y for the two main variables, data= for a DataFrame. Add hue, style, and size to show groups or extra numeric information— sparingly. Customize with Matplotlib ax.set_title(), labels, figure size, and legend placement. Use sns.regplot() for trend lines and sns.relplot(kind="scatter") for faceted scatter plots. See the official scatterplot API for every parameter.

