Subplots in Julia
How to make subplots in with Plotly's Julia graphing library. Examples of stacked, custom-sized, gridded, and annotated subplots.
Plotly Studio: Transform any dataset into an interactive data application in minutes with AI. Try Plotly Studio now.
Note: We are retiring documentation for R, MATLAB, Julia, and F# in November 2025. Learn more about this change here.
Simple Subplot
Figures with subplots are created using Julia's array creation syntax. To create a Figure with one row and two columns of subplots, use the syntax [plot(...) plot(...)]
using PlotlyJS
p1 = plot(scatter(x=1:3, y=4:6))
p2 = plot(scatter(x=20:40, y=50:70))
p = [p1 p2]
relayout!(p, title_text="Side by side layout (1 x 2)")
p
Stacked Subplots
Here is an example of creating a figure with subplots that are stacked on top of each other since there are 3 rows and 1 column in the subplot layout.
using PlotlyJS
make_plot() = plot(scatter(x=1:4, y=rand(4)))
p = [make_plot(); make_plot(); make_plot()]
relayout!(p, height=600, width=600, title_text="Stacked Subplots")
p
Multiple Subplots
Here is an example of creating a 2 x 2 subplot grid and populating each subplot with a single scatter trace.
using PlotlyJS
make_plot() = plot(scatter(x=1:4, y=rand(4)))
[
make_plot() make_plot()
make_plot() make_plot()
]
Or, equivalently
using PlotlyJS
make_plot() = plot(scatter(x=1:4, y=rand(4)))
[make_plot() make_plot(); make_plot() make_plot()]
Multiple Subplots with Titles
To add titles to your subplots, add a title to the Layout of each original plot
Here is an example of adding subplot titles to a 2 x 2 subplot grid of scatter traces.
using PlotlyJS
make_scatter() = scatter(x=1:4, y=rand(4))
p1 = plot(make_scatter(), Layout(title="subplot 1"))
p2 = plot(make_scatter(), Layout(title="subplot 2"))
p3 = plot(make_scatter(), Layout(title="subplot 3"))
p4 = plot(make_scatter(), Layout(title="subplot 4"))
p = [p1 p2; p3 p4]
relayout!(p, height=500, width=700, title_text="Multiple Subplots with Titles")
p
The Subplots type
The array construction pun is helpful for quickly creating grids of regularly spaced subplots.
To do more advanced subplot custimization, we have the Subplots type.
Using the Subplots you can control things like the relative size of subplots, created nested grids of subplots, share x or y axes, etc.
There are two usage patterns for using the Subplots type:
Pattern 1
The first pattern is to directly create an instance of Subplots, then create a Layout, then create an empty plot and add traces
using PlotlyJS
sp = Subplots(kwargs...)
layout = Layout(sp)
p = plot(layout)
add_trace!(p, ...)
Pattern 2
The second pattern is to use the make_subplots helper function that does that for you.
using PlotlyJS
p = make_subplots(kwargs....)
add_trace!(p, ...)
Note that make_subplots takes all the same arguments as Subplots.
Below are some examples of how this works.
Subplots with Shared X-Axes
The shared_xaxes argument to make_subplots can be used to link the x axes of subplots in the resulting figure. The vertical_spacing argument is used to control the vertical spacing between rows in the subplot grid.
Here is an example that creates a figure with 3 vertically stacked subplots with linked x axes. A small vertical spacing value is used to reduce the spacing between subplot rows.
using PlotlyJS
p = make_subplots(rows=3, cols=1, shared_xaxes=true, vertical_spacing=0.02)
add_trace!(p, scatter(x=0:2, y=10:12), row=3, col=1)
add_trace!(p, scatter(x=2:4, y=100:10:120), row=2, col=1)
add_trace!(p, scatter(x=3:5, y=1000:100:1200), row=1, col=1)
relayout!(p, title_text="Stacked Subplots with Shared X-Axes")
p
Subplots with Shared Y-Axes
The shared_yaxes argument to make_subplots can be used to link the y axes of subplots in the resulting figure.
Here is an example that creates a figure with a 2 x 2 subplot grid, where the y axes of each row are linked.
using PlotlyJS
p = make_subplots(rows=3, cols=2, shared_yaxes=true)
add_trace!(p, scatter(x=0:2, y=10:12), row=1, col=1)
add_trace!(p, scatter(x=20:10:40, y=1:3), row=1, col=2)
add_trace!(p, scatter(x=3:5, y=600:100:800), row=2, col=1)
add_trace!(p, scatter(x=3:5, y=1000:100:1200), row=2, col=2)
relayout!(p, title_text="Multiple Subplots with Shared Y-Axes")
p
Custom Sized Subplot with Subplot Titles
The specs argument to make_subplots is used to configure per-subplot options. specs must be a Matrix with dimensions that match those provided as the rows and cols arguments. The elements of specs may either be missing, indicating no subplot should be initialized starting with this grid cell, or an instance of Spec containing subplot options. The colspan subplot option specifies the number of grid columns that the subplot starting in the given cell should occupy. If unspecified, colspan defaults to 1.
Here is an example that creates a 2 by 2 subplot grid containing 3 subplots. The subplot specs element for position (2, 1) has a colspan value of 2, causing it to span the full figure width. The subplot specs element for position (2, 2) is None because no subplot begins at this location in the grid.
using PlotlyJS
p = make_subplots(
rows=2, cols=2,
specs=[Spec() Spec(); Spec(colspan=2) missing],
subplot_titles=["First Subplot" "Second Subplot"; "Third Subplot" missing]
)
add_trace!(p, scatter(x=[1, 2], y=[1, 2]), row=1, col=1)
add_trace!(p, scatter(x=[1, 2], y=[1, 2]), row=1, col=2)
add_trace!(p, scatter(x=[1, 2, 3], y=[2, 1, 2]), row=2, col=1)
relayout!(p, showlegend=false, title_text="Specs with Subplot Title")
p
Multiple Custom Sized Subplots
Here is an example that uses the rowspan and colspan subplot options to create a custom subplot layout with subplots of mixed sizes. The print_grid argument is set to True so that the subplot grid is printed to the screen.
using PlotlyJS
p = make_subplots(
rows=5, cols=2,
specs=[Spec() Spec(rowspan=2)
Spec() missing
Spec(rowspan=2, colspan=2) missing
missing missing
Spec() Spec()]
)
add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(1,1)"), row=1, col=1)
add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(1,2)"), row=1, col=2)
add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(2,1)"), row=2, col=1)
add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(3,1)"), row=3, col=1)
add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(5,1)"), row=5, col=1)
add_trace!(p, scatter(x=[1, 2], y=[1, 2], name="(5,2)"), row=5, col=2)
relayout!(p, height=600, width=600, title_text="specs examples")
p
Subplots Types
By default, the make_subplots function assumes that the traces that will be added to all subplots are 2-dimensional cartesian traces (e.g. scatter, bar, histogram, violin, etc.). Traces with other subplot types (e.g. scatterpolar, scattergeo, parcoords, etc.) are supported by specifying the kind subplot option in the specs argument to make_subplots.
Here are the possible values for the kind option:
"xy": 2D Cartesian subplot type for scatter, bar, etc. This is the default if notypeis specified."scene": 3D Cartesian subplot for scatter3d, cone, etc."polar": Polar subplot for scatterpolar, barpolar, etc."ternary": Ternary subplot for scatterternary."mapbox": Mapbox subplot for scattermapbox."domain": Subplot type for traces that are individually positioned. pie, parcoords, parcats, etc.trace type: A trace type name (e.g.
"bar","scattergeo","carpet","mesh", etc.) which will be used to determine the appropriate subplot type for that trace.
Here is an example that creates and populates a 2 x 2 subplot grid containing 4 different subplot types.
using PlotlyJS
p = make_subplots(
rows=2, cols=2,
specs=[
Spec(kind="xy") Spec(kind="polar")
Spec(kind="domain") Spec(kind="scene")
]
)
add_trace!(p, bar(y=[2, 3, 1]), row=1, col=1)
add_trace!(p, barpolar(theta=[0, 45, 90], r=[2, 3, 1]), row=1, col=2)
add_trace!(p, pie(values=[2, 3, 1]), row=2, col=1)
add_trace!(p,
scatter3d(x=[2, 3, 1], y=[0, 0, 0], z=[0.5, 1, 2], mode="lines"),
row=2, col=2
)
relayout!(p, height=700, showlegend=false)
nothing
Low Level API
The third and last approach for creating subplots is to use the low level plotly.js api.
When using this API you explicitly place each of the axes on the figure and link them to one another.
You also are responsible for assigned traces to a particular pair of axes.
This is the most verbose of the methods for creating charts with multiple subplots, but it is also the most powerful.
The other methods (array creation syntax and make_subplots) use this API under the hood.
Side by Side Subplot (low-level API)
using PlotlyJS
plot(
[
scatter(x=1:3, y=4:6),
scatter(x=20:10:30, y=50:10:70, xaxis="x2", yaxis="y2")
],
Layout(xaxis_domain=[0, 0.7], xaxis2_domain=[0.8, 1], yaxis2_anchor="x2")
)
Subplots with shared axes (low-level API)
using PlotlyJS
plot(
[
scatter(x=1:3, y=4:6),
scatter(x=20:10:30, y=[5, 5, 5], xaxis="x2", yaxis="y"),
scatter(x=2:4, y=600:100:800, xaxis="x", yaxis="y3"),
scatter(x=4000:1000:6000, y=7000:1000:9000, xaxis="x4", yaxis="y4"),
],
Layout(
xaxis_domain=[0, 0.45],
yaxis_domain=[0, 0.45],
xaxis2_domain=[0.55, 1],
xaxis4=attr(domain=[0.55, 1], anchor="y4"),
yaxis3_domain=[0.55, 1],
yaxis4=attr(domain=[0.55, 1], anchor="x4")
)
)
Stacked Subplots with a Shared X-Axis (low-level API)
using PlotlyJS
plot(
[
scatter(x=0:2, y=10:12),
scatter(x=2:4, y=100:10:120, yaxis="y2"),
scatter(x=3:5, y=1000:100:1200, yaxis="y3"),
],
Layout(
yaxis_domain=[0, 0.33],
legend_traceorder="reversed",
yaxis2_domain=[0.33, 0.66],
yaxis3_domain=[0.66, 1]
)
)
Reference
All of the x-axis properties are found here: https://plotly.com/julia/reference/XAxis/ All of the y-axis properties are found here: https://plotly.com/julia/reference/YAxis/
To get more help, see the docstring for make_subplots
using PlotlyJS
@doc make_subplots