Faceting & Subplots in Plotly
Last Updated: 08 Nov 2025
Faceting splits one dataset into multiple small plots by a category — perfect for comparing groups, trends per region, A/B testing, or dashboard panels.
Subplots = Multiple different charts in one figure.
Hinglish Tip: Faceting = "ek data, alag-alag khidkiyon mein dikhao" — jaise photo collage! Subplots = "alag-alag charts ek frame mein" — full dashboard in one go.
1. Faceting with px (Same Chart, Different Groups)
Basic Facet Row/Column
import plotly.express as px
df = px.data.tips()
fig = px.scatter(
df,
x="total_bill",
y="tip",
color="smoker",
facet_col="day", # One plot per day
facet_row="time", # One plot per time (Lunch/Dinner)
title="Tips Analysis by Day & Time"
)
fig.show()
Facet with Bar Chart
fig = px.bar(
df,
x="sex",
y="total_bill",
color="smoker",
facet_col="day",
title="Average Bill by Gender, Smoker, and Day"
)
fig.show()
Control Layout
fig = px.histogram(
df, x="total_bill", color="smoker",
facet_col="day",
facet_col_wrap=2, # Only 2 plots per row
height=600,
title="Bill Distribution by Day (2 per row)"
)
fig.show()
2. Subplots with make_subplots() (Different Charts)
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import plotly.express as px
# Sample data
df = px.data.iris()
# Create 2x2 grid
fig = make_subplots(
rows=2, cols=2,
subplot_titles=("Sepal Length vs Width", "Petal Length vs Width",
"Sepal Length Dist", "Species Count"),
specs=[[{"type": "scatter"}, {"type": "scatter"}],
[{"type": "histogram"}, {"type": "bar"}]]
)
# 1. Scatter: Sepal
fig.add_trace(
go.Scatter(x=df["sepal_length"], y=df["sepal_width"], mode='markers',
marker=dict(color=df["species_id"], colorscale='Viridis'),
name="Sepal"),
row=1, col=1
)
# 2. Scatter: Petal
fig.add_trace(
go.Scatter(x=df["petal_length"], y=df["petal_width"], mode='markers',
marker=dict(color=df["species_id"], colorscale='Plasma'),
name="Petal"),
row=1, col=2
)
# 3. Histogram
fig.add_trace(
go.Histogram(x=df["sepal_length"], name="Sepal Length"),
row=2, col=1
)
# 4. Bar (species count)
species_count = df["species"].value_counts().sort_index()
fig.add_trace(
go.Bar(x=species_count.index, y=species_count.values, name="Count"),
row=2, col=2
)
fig.update_layout(height=700, title_text="Iris Dataset Dashboard (Subplots)")
fig.show()
Hinglish Tip:
make_subplots()→ dashboard banao — scatter, bar, hist ek saath!
3. Faceting + Trendline
fig = px.scatter(
df, x="total_bill", y="tip", color="day",
facet_col="time",
trendline="ols", # Regression line per facet
title="Tip vs Bill with Trendline (Lunch vs Dinner)"
)
fig.show()
4. Shared Axes & Custom Spacing
fig = make_subplots(
rows=1, cols=2,
shared_yaxes=True, # Same Y scale
horizontal_spacing=0.05
)
fig.add_trace(go.Scatter(x=df["total_bill"], y=df["tip"], mode='markers'), row=1, col=1)
fig.add_trace(go.Histogram(x=df["total_bill"]), row=1, col=2)
fig.update_layout(title="Bill vs Tip + Distribution (Shared Y)")
fig.show()
Key Parameters Summary
| Feature | Parameter | Use |
|---|---|---|
| Faceting (px) | facet_row, facet_col | Split by category |
| sd | facet_col_wrap | Wrap long rows |
| Subplots (go) | make_subplots(rows, cols) | Custom grid |
| sd | specs=[[type], [type]] | Mix chart types |
| dfs | shared_xaxes, shared_yaxes | Sync scales |
| Layout | height, title_text | Control size & title |
Common Mistakes to Avoid
| Mistake | Fix |
|---|---|
| Too many facets → unreadable | Limit to 2–6 panels. Use facet_col_wrap |
| Wrong row/col in subplots | Always check row=1, col=2 |
| No titles on subplots | Use subplot_titles=(...) |
| Different scales → misleading | Use shared_yaxes=True |
| Can't export | Install kaleido |