Wolfram Research

Function Repository Resource:

PlotGrid

Source Notebook

Create stacked plots and other advanced grid layouts of plots

Contributed by: Lukas Lang

ResourceFunction["PlotGrid"][{{plt1,1,},}]

arranges the given matrix of plots into a grid where adjacent plots share the frame ticks.

Details and Options

ResourceFunction["PlotGrid"] enables the creation of plots with shared frame ticks.
In ResourceFunction["PlotGrid"][{[plt1,1,},}], the plti,j can be Graphics expressions or Legended graphics expressions.
SpanFromLeft, SpanFromAbove and SpanFromBoth can be used in place of the plti,j to create spanning plots, as is possible for Grid.
The plti,j can also be Null or None, in which case the corresponding grid space is left empty.
ResourceFunction["PlotGrid"] automatically hides frame ticks and labels on shared edges.
The graphics returned by ResourceFunction["PlotGrid"] is freely resizable, with all plots scaling appropriately.
ResourceFunction["PlotGrid"] accepts the same options as Graphics, with the following additions and changes:
AspectRatio Automatic aspect ratio of the plot grid
FrameLabel None outer frame labels, shared by all plots of the grid
FrameStyle Automatic the style of the outer frame and labels
ItemSize Automatic the size of the rows and columns
Spacings None the spacing to leave between the rows and columns
PlotLabels None how to label the individual plots
"ShowFrameLabels" Full which frame labels and tick labels of the plots to show
"HideOuterTickLabels" Full whether to hide outer tick labels to prevent overlaps
"MergeAxes" False whether to merge axes by connecting the frames of adjacent plots
PerformanceGoal "Quality" whether to favor graphics that are fast to render or look better
Method Automatic advanced options to use
In addition to all standard settings, the following settings can be given for AspectRatio:
Automatic automatic value based on the ItemSize setting and aspect ratios of invididual plots
GeometricMean use the geometric mean of all aspect ratios as AspectRatio
Mean use the arithmetic mean of all aspect ratios as AspectRatio
With the default setting AspectRatioAutomatic, multiplying the ItemSize specifications for one dimension by a number scales the aspect ratio by the same amount.
The labels specified by FrameLabel are drawn outside potential frame labels of the inner plots.
With the default setting FrameStyleAutomatic, the style is inherited from the first plot of the grid.
For ItemSize, the following settings can be given for an individual row/column:
Automatic use a constant default size
size use the specified size relative to other rows/columns
Scaled size item relative to the plot range
ImageScaled size item relative to the image size
Scaled [ s ] size by plot range, scaled by a factor s
ImageScaled [ s ] size by image size, scaled by a factor s
Offset [ size ] size in printers points
Offset [ offset , spec ] add offset printers points to the size specified by spec
For ItemSize, the setting Automatic is equivalent to specifying 1.
The settings Scaled and ImageScaled for ItemSize are equivalent to Scaled[1] and ImageScaled[1], respectively.
Specifying n for one item and Automatic for the remaining ones causes it to be n times as big as the rest.
When different types of scalings, e.g. Scaled and ImageScaled[2], are mixed, ResourceFunction["PlotGrid"] effectively tries to convert all specifications to pure size specifications with reasonable conversion factors.
At least one row and one column must use a relative ItemSize setting.
Reference sizes for Scaled and ImageScaled type specifications are only computed from non-spanning plots and can therefore not be used for rows/columns where every plot is spanning.
For Spacings, the following settings can be given for an individual gap between rows/columns:
size size in printers points
Scaled [ s ] fraction s of the plot grid width
The options ItemSize and Spacings support the full range of sequence specifications described in the respective documentation pages.
For PlotLabels, the following settings can be given:
None add no labels
spec use the same specification for all plots
{ spec 1 , } use different specifications for each plot
{ { spec 1,1 , } , } use several labels for a plot
In PlotLabels, the following settings can be given for an individual label specification:
Column format automatically number plot based on format, with plots ordered by columns
Row format number plots ordered by rows
lbl use lbl as label
Placed [ spec , pos ] place label at the specified position
For PlotLabels, Automaticformat is equivalent to Columnformat.
In typeformat type PlotsLabels specifications, the format can be a string or wrapped string, where the first letter/number is replaced by the corresponding number for each plot based on the following table:
a number plots using a, b, c, …
A number plots using A, B, C, …
i number plots using i, ii, iii, …
I number plots using I, II, III, …
1 number plots using 1, 2, 3, …
The position in Placed[spec,pos] type PlotLabels specifications supports similar settings as used by PlotLegends placement; in particular, the following settings can be used:
Left , Above , symbolic specifications
{ x , y } explicit settings for horizontal and vertical positioning
ImageScaled [ { x , y } ] numeric position which does not try to avoid the frame of the plots
Offset [ { dx , dy } , spec ] position offset by the specified number of printers points
For numeric position specifications, values below 0 are left of/below the plot, values above 1 are right of/above the plot, and values in between are inside the plot frame.
If no position is specified for a label, {Left,Top} is used as default.
By default, label placement tries to avoid the frame of the plot, placing labels either inside the plot range or outside the frame. Using ImageScaled[pos] type coordinates overrides this behavior.
Labels can also be specified for individual plots using Labeled wrappers of the form Labeled[plot,lbl,].
For "ShowFrameLabels", the following settings can be given for an individual plot:
Automatic show frame labels if there is no adjacent plot
Full show frame labels if there is a gap or no adjacent plot
All or True show all frame labels
None or False show no frame labels
{ hspec , vspec } use separate settings for the horizontal and vertical frame edges
{ { left , right } , { bottom , top } } use different settings for each side
{ side 1 spec 1 , } use the specified setting for the specified side
{ def , side 1 spec 1 , } use def for sides where no explicit value is given
The option "ShowFrameLabels" supports the same specifications to specify individual items as described in the documentation of ItemStyle.
In the setting for "ShowFrameLabels", Directive can be used instead of List to indicate that a specification should be interpreted as one instead of a sequence for different items.
In "ShowFrameLabels" settings, the sidei can be Left, Right, Top or Bottom.
With the default setting "ShowFrameLabels"Full, labels are hidden for grids with merged axes, but stay visible for layouts with spacing between the plots.
The options "HideOuterTickLabels" and "MergeAxes" operate on the boundaries between rows/columns of plots and support the same sequence specifications as described for Spacings.
For each pair of neighboring rows/columns, the following settings can be given for "HideOuterTickLabels":
sideSpec Automatic which sides the hiding should be applied to
methodSpec Full when to apply the hiding based on the existence of neighboring plots and spacings
threshold Automatic up to which distance from the edge to hide individual tick labels
{ sideSpec , methodSpec , threshold } { Automatic , Full , Automatic } specify values for all three parts of the setting
In {sideSpec,methodSpec,threshold}, any subset of the settings can be omitted, e.g. {sideSpec,threshold} or {methodSpec} are both valid.
The hiding strategy for "HideOuterTickLabels" consists of three steps: For each pair of neighboring rows/colums, decide to which side(s) (if any) to apply the hiding based on sideSpec. Look whether there is a neighboring plot or spacing, and decide whether still to hide tick labels based on methodSpec. Use threshold to hide the tick labels that are too close to the edge.
In "HideOuterTickLabels"{sideSpec,}, the following settings can be given for sideSpec:
Automatic hide the tick labels on the bottom/left plots
First hide the tick labels on the plots that appear first in the grid
Last hide the tick labels on the plots that appear last in the grid
All or True hide on both sides
None or False hide none of the labels
Left and Top can be used in place of First for increased readability. Similarly, Right and Bottom can be used instead of Last.
In "HideOuterTickLabels"{,methodSpec,}, the following settings can be given for methodSpec:
Automatic apply hiding everywhere there is a neighboring plot
Full apply hiding only if there is a neighboring plot with no spacing
All or True apply hiding to all sides
None or False do not apply hiding to any side
In "HideOuterTickLabels"{,threshold}, the following settings can be given for threshold:
Automatic automatically choose threshold
thres a distance threshold in printers points
Scaled [ thres ] a distance threshold as a fraction of the plot range
A threshold setting of Automatic is equivalent to 10 with PerformanceGoal"Quality" and -∞ with PerformanceGoal"Speed".
The default setting "HideOuterTickLabels"Full is equivalent to specifying {Automatic,Full,Automatic} and hides the tick labels of directly adjacent plots (on the left/bottom plot respectively) if they are closer than 10 printers points from the edge, assuming PerformanceGoal"Quality" is set.
The distance check for thresholds given in printers points is made assuming the initial size of the grid and may not be accurate if the grid is resized afterwards.
In case of ambiguity, settings are always interpreted as methodSpec first instead of sideSpec. This means that "HideOuterTickLabels"All is equivalent to {Automatic,All,Automatic}, and not {All,Full,Automatic}.
For each pair of neighboring rows/columns, the following settings can be given for "MergeAxes":
False do not merge the axes
"type" use a named merge indicator
"type"size use the specified size for the merge indicator
{ expr 1 , expr 2 } use the specified expression as merge indicators on either size of the gap
{ expr , Automatic } use a rotated version of one expression for both sides
expr use a single expression
{ spec , width } specify the width of the indicator in printers points
None draw no extra primitives
The following named merge indicators are supported:
"ZigZag"
"Cut"
"Wave"
"Dotted"
"Line"
In "type"size, the size specifies the length of the feature (e.g. the length of the dashed line) of the indicator in printers points. The default size is 10 printers points.
The merge indicator inherits the style from the frames of the two plots, with each half inheriting the style of the respective plot. For expr type specifications, the style of the left/top plot is inherited.
In general, any expression can be used as merge indicator. For proper alignment, a Graphics expression should be used, with the {0,0} point at the point where the primitive connects to the frame. To ensure sizing works as expected, AspectRatioFull should be set.
Due to antialiasing, the alignment of the merge indicators might not be perfect for all sizes of the resulting plot grid. Resizing it slightly will fix the issue in those cases.
In the settings for "HideOuterTickLabels" and "MergeAxes", Directive can be used instead of List to indicate that a specification should be interpreted as one instead of a sequence for different items.
For "ShowFrameLabels", "HideOuterTickLabels" and "MergeAxes", settings can be specified on a per-plot basis using Frame[plot,opts] type wrappers, e.g. Frame[plot,"ShowFrameLabels"None].
For PerformanceGoal, the following settings can be given:
"Quality" Favor high-quality results over fast-to-render ones
"Speed" Reduce number of custom frame ticks to improve resizing performance
The setting of PerformanceGoal affects the defaults of the "HideOuterTickLabels" threshold and of the "AllCustomTicks" Method suboption.
The following Method suboptions can be given:
"FixFrameTicks" True whether to attempt to fix the length of custom ticks
"AllCustomTicks" Automatic whether to use custom ticks for all frame ticks
With the default setting "FixFrameTicks"True, the tick lengths of custom tick specifications are rescaled to work around a bug caused by using AspectRatioFull with custom ticks.
The workaround used by "FixFrameTicks"True estimates the effective aspect ratio of the plots, and may therefore result in suboptimal results if the grid is significantly resized after creation.
The setting "AllCustomTicks" can be used to control whether a custom tick function should be used for all sides that are set to Automatic, True or All to ensure a more uniform result. This might be necessary since the ticks generated by those settings cannot be fully reproduced in all cases.
The default setting "AllCustomTicks"Automatic uses custom ticks only in the event that any default tick specification already needed to be replaced, e.g. to hide the outer tick labels, and only if PerformanceGoal"Quality" is set.
ResourceFunction["PlotGrid"] returns a Graphics expression or a Legended graphics expression.
ResourceFunction["PlotGrid"] will move all legends that are outside of the individual plots to the outside of the entire grid, while leaving those inside in place.
ResourceFunction["PlotGrid"] sets CoordinatesToolOptions to enable extraction of coordinates from any of the plots. The format of the points is {{i,j},{x,y}}, where i,j are the indices of the plot and x,y the coordinates in the coordinate system of the plot.

Examples

Basic Examples

Create two plots sharing the y axis:

In[1]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[x, {x, 0, 1}, Frame -> True],
   Plot[x^2, {x, 0, 1}, Frame -> True]
   }
  }
 ]
Out[1]=

Create two plots stacked vertically:

In[2]:=
ResourceFunction["PlotGrid"][
 {
  {Plot[x, {x, 0, 1}, Frame -> True]},
  {Plot[x^2, {x, 0, 1}, Frame -> True]}
  }
 ]
Out[2]=

Specify a label for the shared axes:

In[3]:=
ResourceFunction["PlotGrid"][
 {
  {Plot[x, {x, 0, 1}, Frame -> True]},
  {Plot[x^2, {x, 0, 1}, Frame -> True]}
  },
 FrameLabel -> {"x axis", "y axis"}
 ]
Out[3]=

The legends of individual plots are combined:

In[4]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[
    {x, x^3},
    {x, 0, 1},
    Frame -> True,
    PlotLegends -> "Expressions"
    ]
   },
  {
   Plot[
    {x^2, x^4},
    {x, 0, 1},
    Frame -> True,
    PlotLegends -> "Expressions"
    ]
   }
  },
 FrameLabel -> {"x-axis", "y-axis"}
 ]
Out[4]=

Scope

Make a 2×2 grid of plots:

In[5]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {
   Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True]
   }
  }
 ]
Out[5]=

Omit one plot, creating an L-shaped grid:

In[6]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], Null}
  }
 ]
Out[6]=

Make the bottom plot span over both columns:

In[7]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30
 ]
Out[7]=

Label the individual plots:

In[8]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Row -> Style["a)", 20]
 ]
Out[8]=

If the legends are inside a plot, they are not moved:

In[9]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[
    {x, x^3},
    {x, 0, 1},
    Frame -> True,
    PlotLegends -> Placed["Expressions", {Left, Top}]
    ]
   },
  {
   Plot[
    {x^2, x^4},
    {x, 0, 1},
    Frame -> True,
    PlotLegends -> Placed["Expressions", {Left, Top}]
    ]
   }
  },
 FrameLabel -> {"x-axis", "y-axis"}
 ]
Out[9]=

Options

FrameLabel

Labels specified by FrameLabel are centered with respect to the full plot grid:

In[10]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   }
  },
 FrameLabel -> {"x axis", "y axis"}
 ]
Out[10]=

Label both individual frame axes and the whole group:

In[11]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[
    x, {x, 0, 1}, Frame -> True, FrameLabel -> {None, "y-axis 1"}
    ]
   },
  {
   Plot[
    x^2,
    {x, 0, 1},
    Frame -> True,
    FrameLabel -> {None, "y-axis 2"}
    ]
   }
  },
 FrameLabel -> {None, "y-axes"}
 ]
Out[11]=

FrameStyle

The setting for FrameStyle affects the frame labels shared by all plots:

In[12]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[
    x, {x, 0, 1}, Frame -> True, FrameLabel -> {None, "y-axis 1"}
    ]
   },
  {
   Plot[
    x^2,
    {x, 0, 1},
    Frame -> True,
    FrameLabel -> {None, "y-axis 2"}
    ]
   }
  },
 FrameLabel -> {None, "y-axes"},
 FrameStyle -> FontSize -> 16
 ]
Out[12]=

With the default setting FrameStyleAutomatic, the style is inherited from the first plot:

In[13]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[
    x,
    {x, 0, 1},
    Frame -> True,
    FrameLabel -> {None, "y-axis 1"},
    FrameStyle -> Red
    ]
   },
  {
   Plot[
    x^2,
    {x, 0, 1},
    Frame -> True,
    FrameLabel -> {None, "y-axis 2"},
    FrameStyle -> Red
    ]
   }
  },
 FrameLabel -> {None, "y-axes"}
 ]
Out[13]=

ItemSize

With the default setting ItemSizeAutomatic, all rows and columns have the same size:

In[14]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ]
 ]
Out[14]=

Make the middle row twice as high:

In[15]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 ItemSize -> {Automatic, {2 -> 2}}
 ]
Out[15]=

Size the rows and columns according to the plot ranges:

In[16]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 ItemSize -> Scaled
 ]
Out[16]=

Size the rows and columns according to the plot ranges, but make the third column half as wide:

In[17]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 ItemSize -> {{{Scaled}, Scaled[0.5]}, Scaled}
 ]
Out[17]=

Make the first row and column 100 printers points big:

In[18]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 ItemSize -> {{Offset[100]}, {Offset[100]}}
 ]
Out[18]=

The remaining space is dynamically filled by the remaining rows and columns:

In[19]:=
Manipulate[
 ResourceFunction["PlotGrid"][
  Table[
   Graphics[
    Text[{i, j}],
    PlotRange -> 1.2 {{-j, j}, {-i, i}},
    Frame -> True
    ],
   {i, 3},
   {j, 3}
   ],
  ItemSize -> {{Offset[100]}, {Offset[100]}},
  ImageSize -> Dynamic[size],
  PerformanceGoal -> "Speed"
  ],
 {size, 200, 600}
 ]
Out[19]=

Spacings

With the default setting SpacingsNone, no space is left between rows and columns:

In[20]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ]
 ]
Out[20]=

Separate plots by 30 printers points:

In[21]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> 30
 ]
Out[21]=

Separate plots by 10% of the total plot grid width:

In[22]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> Scaled[0.1]
 ]
Out[22]=

Only insert space between rows:

In[23]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {None, Scaled[0.1]}
 ]
Out[23]=

With "ShowFrameLabels"Full, frame labels and ticks are shown if there is a gap:

In[24]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {None, Scaled[0.1]},
 "ShowFrameLabels" -> Full
 ]
Out[24]=

PlotLabels

With the default settings PlotLabelsNone, the plots are not labeled:

In[25]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30
 ]
Out[25]=

Label the plots columns-first using a),b),…:

In[26]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Automatic -> "a)"
 ]
Out[26]=

Apply styling to the labels and use sequential numbers.:

In[27]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Automatic -> Style["1.", 20, Black]
 ]
Out[27]=

Place the labels outside the plots, and number rows-first:

In[28]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Placed[Row -> "i)", {Left, Above}]
 ]
Out[28]=

The base style of the labels is affected by LabelStyle:

In[29]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Placed[Row -> "i)", {Left, Above}],
 LabelStyle -> {Black, 15}
 ]
Out[29]=

Add an additional custom label to one of the plots using a Labeled wrapper:

In[30]:=
ResourceFunction["PlotGrid"][
 {
  {
   Labeled[
    Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
    "A label",
    {Left, Top}
    ],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Placed[Row -> "i)", {Left, Above}]
 ]
Out[30]=

If the same position is specified for multiple labels, overlap is automatically avoided:

In[31]:=
ResourceFunction["PlotGrid"][
 {
  {
   Labeled[
    Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
    "A label",
    {Left, Above}
    ],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Placed[Row -> "i)", {Left, Above}]
 ]
Out[31]=

ShowFrameLabels

With the default setting "ShowFrameLabels"Full, frame ticks and labels are shown if there is no adjacent plot or a spacing:

In[32]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {None, 20}
 ]
Out[32]=

Labels are shown if a plot is omitted:

In[33]:=
ResourceFunction["PlotGrid"][
 ReplacePart[
  Table[
   Graphics[
    Text[{i, j}],
    PlotRange -> 1.2 {{-j, j}, {-i, i}},
    Frame -> True
    ],
   {i, 3},
   {j, 3}
   ],
  {2, 2} -> Null
  ],
 Spacings -> {None, 20}
 ]
Out[33]=

Hide all labels unless there is no adjacent plot at all:

In[34]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {None, 20},
 "ShowFrameLabels" -> Automatic
 ]
Out[34]=

Show no frame labels:

In[35]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {None, 20},
 "ShowFrameLabels" -> None
 ]
Out[35]=

Show all frame labels:

In[36]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> 1.2 {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {None, 20},
 "ShowFrameLabels" -> All
 ]
Out[36]=

Hide frame labels of the center plot using a Frame[plot,] type wrapper:

In[37]:=
ResourceFunction["PlotGrid"][
 MapAt[
  Frame[#, "ShowFrameLabels" -> None] &,
  Table[
   Graphics[
    Text[{i, j}],
    PlotRange -> 1.2 {{-j, j}, {-i, i}},
    Frame -> True
    ],
   {i, 3},
   {j, 3}
   ],
  {2, 2}
  ],
 Spacings -> {None, 20}
 ]
Out[37]=

HideOuterTickLabels

With the default setting "HideOuterTickLabels"Full, the rightmost tick label on each plot to the left of another plot is hidden if there is insufficient Spacings. Similarly, the topmost tick label on each plot below another plot is hidden:

In[38]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {{None, 30}, {None, 30}}
 ]
Out[38]=

Hide the labels on both plots, not only the left/bottom one:

In[39]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {{None, 30}, {None, 30}},
 "HideOuterTickLabels" -> Directive[All, Full]
 ]
Out[39]=

Also hide outer labels if there is spacing between the plots:

In[40]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {{None, 30}, {None, 30}},
 "HideOuterTickLabels" -> Automatic
 ]
Out[40]=

Hide labels in the outer 50% of the plot range instead of the default 10 printers points. The hiding is done in the default locations, meaning only on the top rows and left columns and never on the outermost edges:

In[41]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {{None, 30}, {None, 30}},
 "HideOuterTickLabels" -> Scaled[0.5]
 ]
Out[41]=

Do not hide any tick labels, potentially causing overlaps:

In[42]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {None, 20},
 "HideOuterTickLabels" -> None
 ]
Out[42]=

Hide the outer ticks on the lower right plot only by specifying the setting using a Frame[plot,] type wrapper:

In[43]:=
ResourceFunction["PlotGrid"][
 MapAt[
  Frame[#, "HideOuterTickLabels" -> {Directive[Right, All, 30], None}] &,
  Table[
   Graphics[
    Text[{i, j}],
    PlotRange -> {{-j, j}, {-i, i}},
    Frame -> True
    ],
   {i, 3},
   {j, 3}
   ],
  {3, 3}
  ],
 Spacings -> {None, 20},
 "HideOuterTickLabels" -> None
 ]
Out[43]=

MergeAxes

With the default setting "MergeAxes"False, the axes of the plots are not merged:

In[44]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True], SpanFromLeft}
  },
 Spacings -> 30
 ]
Out[44]=

Merge the axes of the left two plots using a zig-zag line:

In[45]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False], SpanFromAbove}
  },
 Spacings -> 30,
 "MergeAxes" -> {False, "ZigZag"}
 ]
Out[45]=

Use a cut-type indicator instead, and make the gap larger:

In[46]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False], SpanFromAbove}
  },
 Spacings -> 30,
 "MergeAxes" -> {False, "Cut" -> 30}
 ]
Out[46]=

The frame styles of both plots are inherited:

In[47]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Red],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Blue], SpanFromAbove}
  },
 Spacings -> 30,
 "MergeAxes" -> {False, Directive["Wave" -> 20, 20]}
 ]
Out[47]=

Specify which axes to merge using a Frame[plot,] type wrapper instead:

In[48]:=
ResourceFunction["PlotGrid"][
 {
  {
   Frame[
    Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Red],
    "MergeAxes" -> {False, "Dotted" -> 20}
    ],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Blue], SpanFromAbove}
  },
 Spacings -> 30
 ]
Out[48]=

Use a custom merge indicator:

In[49]:=
ResourceFunction["PlotGrid"][
 {
  {
   Frame[
    Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Red],
    "MergeAxes" -> {False, {Graphics[Rectangle[{0, -1}, {1, 1}], PlotRange -> {{0, 1}, {-1, 1}}, PlotRangePadding -> None, AspectRatio -> Full], Automatic}}
    ],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Blue], SpanFromAbove}
  },
 Spacings -> 30
 ]
Out[49]=

Use a different merge indicator on each side of the gap:

In[50]:=
ResourceFunction["PlotGrid"][
 {
  {
   Frame[
    Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Red],
    "MergeAxes" -> {
      False,
      {
       Graphics[{Arrowheads@1, Arrow@{{0, 0}, {1, 0}}}, PlotRange -> {{0, 1}, {-1, 1}}, PlotRangePadding -> None, AspectRatio -> Full],
       Graphics[{Arrowheads@1, Arrow@{{1, 0}, {0, 0}}}, PlotRange -> {{0, 1}, {-1, 1}}, PlotRangePadding -> None, AspectRatio -> Full]
       }
      }
    ],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True, Axes -> False, FrameStyle -> Blue], SpanFromAbove}
  },
 Spacings -> 30
 ]
Out[50]=

PerformanceGoal

Setting PerformanceGoal to "Speed" can drastically improve the performance when resizing the plot grid due to an issue in the front-end related to custom ticks:

In[51]:=
Manipulate[
 ResourceFunction["PlotGrid"][
  Table[
   Graphics[
    Text[{i, j}],
    PlotRange -> 1.2 {{-j, j}, {-i, i}},
    Frame -> True
    ],
   {i, 3},
   {j, 3}
   ],
  ItemSize -> {{Offset[100]}, {Offset[100]}},
  ImageSize -> Dynamic[size],
  PerformanceGoal -> perfGoal
  ],
 {size, 200, 600},
 {perfGoal, {"Speed", "Quality"}}
 ]
Out[51]=

Method

With the default setting "FixFrameTicks"True, the tick length is corrected to appear as expected:

In[52]:=
ResourceFunction["PlotGrid"][
 {{
   DateListPlot[{1, 1, 2, 3, 5, 8, 11}, {2000, 8}],
   DateListPlot[{1, 1, 2, 3, 5, 8, 11}, {2000, 8}]
   }}
 ]
Out[52]=

Turning the fix off might yield unexpected results:

In[53]:=
ResourceFunction["PlotGrid"][
 {{
   DateListPlot[{1, 1, 2, 3, 5, 8, 11}, {2000, 8}],
   DateListPlot[{1, 1, 2, 3, 5, 8, 11}, {2000, 8}]
   }},
 Method -> {"FixFrameTicks" -> False}
 ]
Out[53]=

With the default setting "AllCustomTicks"Automatic, ticks are ensured to be uniform, even if this means differences to the default tick positioning:

In[54]:=
plots = {{
   Plot[x, {x, 0, 3}, Frame -> True],
   Plot[x, {x, 0, 3}, Frame -> True]
   }}
Out[54]=
In[55]:=
ResourceFunction["PlotGrid"][plots]
Out[55]=

Use "AllCustomTicks"False to use custom ticks only where necessary, e.g. to hide tick labels selectively:

In[56]:=
ResourceFunction["PlotGrid"][
 plots,
 Method -> {"AllCustomTicks" -> False}
 ]
Out[56]=

Possible Issues

PlotGrid assumes that plots have compatible plot ranges:

In[57]:=
ResourceFunction["PlotGrid"][
 {{
   Plot[x, {x, 0, 3}, Frame -> True],
   Plot[x^2, {x, 0, 3}, Frame -> True]
   }}
 ]
Out[57]=

Tick labels are hidden based on the size the grid is generated with; therefore, changing it later might lead to unexpected results:

In[58]:=
Show[
 ResourceFunction["PlotGrid"][
  {{
    Plot[x, {x, 0, 2.65}, Frame -> True],
    Plot[x, {x, 0, 3}, Frame -> True]
    }}
  ],
 ImageSize -> 250
 ]
Out[58]=

Specify the size directly instead:

In[59]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[x, {x, 0, 2.65}, Frame -> True],
   Plot[x, {x, 0, 3}, Frame -> True]
   }
  },
 ImageSize -> 250
 ]
Out[59]=

The ticks might sometimes be changed by PlotGrid:

In[60]:=
plots = {{
   Plot[x, {x, 0, 3}, Frame -> True],
   Plot[x, {x, 0, 3}, Frame -> True]
   }}
Out[60]=
In[61]:=
ResourceFunction["PlotGrid"][plots]
Out[61]=

To recover the original ticks, disable both "HideOuterTickLabels" and "AllCustomTicks":

In[62]:=
ResourceFunction["PlotGrid"][
 plots,
 "HideOuterTickLabels" -> None,
 Method -> {"AllCustomTicks" -> False}
 ]
Out[62]=

Invalid specifications for spanning plots lead to leftover span indicators:

In[63]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   SpanFromAbove
   },
  {
   SpanFromLeft,
   SpanFromBoth
   }
  },
 Spacings -> 30
 ]
Out[63]=

Neat Examples

Use PlotGrid to create new types of compound plots:

In[64]:=
data =
  RandomVariate[
   BinormalDistribution[{0, 0}, {1, 2}, 0.6], 1000
   ];
ResourceFunction["PlotGrid"][
 {
  {
   Histogram[
    data[[All, 2]],
    20,
    BarOrigin -> Left,
    Frame -> True,
    FrameTicks -> {{True, False}, {False, False}},
    PlotRange -> {Automatic, {-7, 7}},
    PlotRangePadding -> 0,
    GridLines -> {None, Automatic}
    ],
   ListPlot[
    data,
    Axes -> False,
    Frame -> True,
    GridLines -> Automatic,
    PlotRangePadding -> 0,
    PlotRange -> {{-4, 4}, {-7, 7}}
    ]
   },
  {
   Graphics[
    {},
    Frame -> True,
    FrameTicks -> None
    ],
   Histogram[
    data[[All, 1]],
    20,
    Frame -> True,
    FrameTicks -> {{False, False}, {True, False}},
    PlotRange -> {{-4, 4}, Automatic},
    PlotRangePadding -> 0,
    GridLines -> {Automatic, None}
    ]
   }
  },
 ItemSize -> {{1, 3}, {3, 1}},
 "MergeAxes" -> None
 ]
Out[65]=

Resource History

Source Metadata

Related Resources

Author Notes

Changes from version 1.1.0 to 1.2.0:

Added PlotLabels option and support for Labeled wrappers
Added "MergeAxes" option
Added support for Frame wrappers to set "ShowFrameLabels", "HideOuterTickLabels" and "MergeAxes"
Added PerformanceGoal option & changed default "HideOuterTickLabels" threshold from 10 to Automatic
Fixed padding determination in certain layouts involving spanning plots
Fixed "HideOuterLabels" not working as expected in certain cases involving spanning plots
Fixed frame tick labels not being hidden as expected in certain cases
Change the graphics structure to enable the use of ImagePaddingAutomatic at the top-level, which is now the default
Fixed PlotGrid not working with non-standard Evaluator

Changes from version 1.0.0 to 1.1.0:

Added support for spanning plots
Updated the AspectRatio determination for Automatic to take the relative sizes of ItemSize widths and height into account
Added "HideOuterTickLabels" to prevent overlapping tick labels
Improved logic to decide whether a legend is inside or outside the plot
Fixed the "CopiedValueFunction" to copy the correct value in (almost) all cases
Fixed an issue when combining Scaled/ImageScaled type ItemSize specifications with number style specifications
Changed the default of "ShowFrameLabels" from Automatic to Full to make the two most common use cases (merged axes and gridded layout of unrelated plots) easier to access
Improved merging of composite option values, e.g. "ShowFrameLabels"{Automatic,{All,2{LeftTrue}}} is now equivalent to "ShowFrameLabels"{Automatic,{All,2{All,LeftTrue}}} instead of "ShowFrameLabels"{Automatic,{Full,2{LeftTrue}}}
Added "FixTickLength" Method suboption to work around an issue with AspectRatioFull and custom ticks
Added "AllCustomTicks" Method suboption to ensure that ticks are all consistent when replacing All/Automatic ticks with customized versions (needed to selectively hide labels)
Improved the method used to hide tick labels to handle non-text based ticks properly
Fixed an issue where PlotLabel would be spaced too far apart from the actual plots

License Information