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

FeatureParameterUse
Faceting (px)facet_row, facet_colSplit by category
sdfacet_col_wrapWrap long rows
Subplots (go)make_subplots(rows, cols)Custom grid
sdspecs=[[type], [type]]Mix chart types
dfsshared_xaxes, shared_yaxesSync scales
Layoutheight, title_textControl size & title

Common Mistakes to Avoid

MistakeFix
Too many facets → unreadableLimit to 2–6 panels. Use facet_col_wrap
Wrong row/col in subplotsAlways check row=1, col=2
No titles on subplotsUse subplot_titles=(...)
Different scales → misleadingUse shared_yaxes=True
Can't exportInstall kaleido