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:
AspectRatioAutomaticaspect ratio of the plot grid
FrameLabelNoneouter frame labels, shared by all plots of the grid
FrameStyleAutomaticthe style of the outer frame and labels
ItemSizeAutomaticthe size of the rows and columns
SpacingsNonethe spacing to leave between the rows and columns
PlotRangeInheritedrow- and column-wise plot ranges
PlotLabelsNonehow to label the individual plots
LabelingFunctionAutomaticpost-processing function for plot labels
Prolog{}list of graphics primitives to be rendered behind the main content
Epilog{}list of graphics primitives to be rendered above the main content
"ShowFrameLabels"Fullwhich frame labels and tick labels of the plots to show
"HideOuterTickLabels"Fullwhether to hide outer tick labels to prevent overlaps
"MergeAxes"Falsewhether to merge axes by connecting the frames of adjacent plots
PerformanceGoal"Quality"whether to favor graphics that are fast to render or look better
MethodAutomaticadvanced options to use
In addition to all standard settings, the following settings can be given for AspectRatio:
Automaticautomatic value based on the ItemSize setting and aspect ratios of invididual plots
GeometricMeanuse the geometric mean of all aspect ratios as AspectRatio
Meanuse the arithmetic mean of all aspect ratios as AspectRatio
{{i1,j1}spec1,}ensure that the plots at position i1,j1 has the AspectRatio specified by spec1
{gridSpec,{i1,j1}spec1,}target the AspectRatio specified by gridSpec for the entire plot grid
With the default setting AspectRatioAutomatic, multiplying the ItemSize specifications for one dimension by a number scales the aspect ratio by the same amount.
Settings of the form AspectRatio{,{ik,jk}speck,} effectively forces the plot at position ik,jk to have a certain aspect ratio.
In AspectRatio{,{ik,jk}speck,}, the speck can be any of the following:
speca standard AspectRatio specification
Inheritedtake the setting from the affected plot itself
In AspectRatio{,{ik,jk}speck,}, the position specifications {ik,jk} can be any of the following:
{ik,jk}the plot at position ik,jk
Alluse the setting for all plots
Automaticuse the setting for as many plots as possible
Due to technical limitations, settings of the form AspectRatio{,{ik,jk}speck,} are only supported if neither the ItemSize nor the Spacings settings contain any specifications in printers points.
Given a setting AspectRatio{,{ik,jk}speck,}, ResourceFunction["PlotGrid"] attempts to fulfill the constraints by varying the aspect ratio of the entire grid, as well as the dimensions of rows/columns with ItemSize set to Automatic.
Not all settings for AspectRatio can be realized. In particular, specifying the AspectRatio for too many individual plots or the ItemSize for too many rows/columns may result in an overconstrained problem without any solutions.
Specifying any per-plot AspectRatio or using a setting of the form AspectRatio{} effectively changes how ItemSize specifications of type Automatic are resolved.
Adding a specification of the form Automaticspec to the setting for AspectRatio will never result in an overconstrained problem.
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:
Automaticuse an automatically determined size
sizeuse the specified size relative to other rows/columns
Scaledsize item relative to the plot range
ImageScaledsize 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, except when using an AspectRatio setting of the form AspectRatio{,{ik,jk}speck,}.
The settings Scaled and ImageScaled for ItemSize are equivalent to Scaled[1] and ImageScaled[1], respectively.
Specifying n for one item and 1 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:
sizesize 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.
The setting for PlotRange controls the horizontal plot ranges per column and the vertical plots ranges per row.
For each row/column, the following settings can be given for PlotRange:
Inheriteddo not adjust the plot range of the individual plots
Maxuse a plot range containing all individual ranges within the row/column
Minuse a plot range contained within all individual ranges within the row/column
specuse a standard PlotRange setting
{lower,uppper}use separate settings for the lower and upper bounds
The setting Min sets the plot range of all plots in a row/column to the largest range contained within all plot ranges of the individual plots. Similarly, the setting Max sets the plot range to the smallest range containing all individual ranges.
PlotRange supports all standard settings for plot range limits such as Automatic, All or numeric limits.
With the default setting PlotRangeInherited, the plot ranges of all plots will be left unchanged.
A common setting is PlotRangeMax, which ensures that the vertical/horizontal plot ranges of all plots within each row/column are consistent and that all data are shown.
The option PlotRange supports the same specifications to specify individual rows/columns as described in the documentation of ItemSize.
For PlotLabels, the following settings can be given:
Noneadd no labels
specuse the same specification for all plots
{spec1,}use different specifications for each plot
{{spec1,1,},}use several labels for a plot
{{{spec1,1,1,},},…}use several top-level label lists
Placed[{},pos]place labels at the specified position
In PlotLabelsspec, Placed wrappers can be placed at any level to specify label positioning, with the innermost specification taking precedence.
The form PlotLabels {{{spec1,1,1,},},} is useful in the form PlotLabels{spec,{{spec1,1,1,},}}, where spec is applied to all plots, and the speci,j,k are applied to individual plots plotj.
In case of ambiguity, label specifications given as nested lists are interpreted as several labels per plot instead of multiple top-level label lists. To ensure the specification is interpreted differently, an empty specification of the form {{}} can be added, as in PlotLabels{spec,{spec1,1,},{{}}}.
In PlotLabels, the following settings can be given for an individual label specification:
Columnformatautomatically number plot based on format, with plots ordered by columns
Rowformatnumber plots ordered by rows
lbluse lbl as label
Placed[spec,pos]place label at the specified position
For PlotLabels, Automaticformat is equivalent to Columnformat.
In typeformat type PlotLabels 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:
anumber plots using a, b, c, …
Anumber plots using A, B, C, …
inumber plots using i, ii, iii, …
Inumber plots using I, II, III, …
1number 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 LabelingFunction, the following settings can be given:
Automaticautomatically combine labels vertically or horizontally
funcuse func to arrange labels
(Automaticfunc)wrap the arranged labels with func
In LabelingFunctionfunc, func is called with a list of all labels for each position.
In LabelingFunction(Automaticfunc), func is called with a single row/column construct that contains all labels for a given position.
In the setting for Prolog and Epilog, {i,j}pos can be used for any of the coordinates to indicate that the position pos is to be interpreted in the coordinate system of the plot with index {i,j}. This enables the creation of annotations linking positions of different plots.
Position specifications of the form {i,j}pos in Prolog and Epilog support any of the standard position specifications for pos, such as {x,y}, Scaled[], ImageScaled[], Offset[], and any mixture of those.
In the setting for Prolog and Epilog, "normal" position specifications are taken to be in the coordinate system of the plot grid itself, with runs from 0 to 1 on both axes. This range excludes the outer frame labels.
For "ShowFrameLabels", the following settings can be given for an individual plot:
Automaticshow frame labels if there is no adjacent plot
Fullshow frame labels if there is a gap or no adjacent plot
All or Trueshow all frame labels
None or Falseshow 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
{side1spec1,}use the specified setting for the specified side
{def,side1spec1,}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":
sideSpecAutomaticwhich sides the hiding should be applied to
methodSpecFullwhen to apply the hiding based on the existence of neighboring plots and spacings
thresholdAutomaticup 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: In each pair of neighboring rows/columns, 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:
Automatichide the tick labels on the bottom/left plots
Firsthide the tick labels on the plots that appear first in the grid
Lasthide the tick labels on the plots that appear last in the grid
All or Truehide on both sides
None or Falsehide 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:
Automaticapply hiding everywhere there is a neighboring plot
Fullapply hiding only if there is a neighboring plot with no spacing
All or Trueapply hiding to all sides
None or Falsedo not apply hiding to any side
In "HideOuterTickLabels"{,threshold}, the following settings can be given for threshold:
Automaticautomatically choose threshold
thresa 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":
Falsedo not merge the axes
"type"use a named merge indicator
"type"sizeuse the specified size for the merge indicator
{expr1,expr2}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
expruse a single expression
{spec,width}specify the width of the indicator in printers points
Style[spec,style1,]apply a custom style to the merge indicators
Nonedraw 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. Custom styles specified via Style[spec,style1,] take precedence over these inherited styles.
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. The indicator will be sized to span the entire gap, so most indicators should only fill half of the plot range.
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 AspectRatio, "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 performance, especially while resizing
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"Truewhether to attempt to fix the length of custom ticks
"AllCustomTicks"Automaticwhether 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. (this does not work in version 12.3, where the tool is disabled to prevent a front-end crash)

Examples

Basic Examples (4) 

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]=

Stack the plots vertically and specify a label for the shared axes:

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

The legends of individual plots are combined:

In[3]:=
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[3]=

See the PlotGridDoc paclet for many additional examples.

Scope (4) 

Create a 2x2 grid of plots with one missing, resulting in an L-shaped grid:

In[4]:=
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[4]=

Make the bottom plot span over both columns and label the individual 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], SpanFromLeft}
  },
 Spacings -> 30,
 PlotLabels -> Row -> Style["a)", 20]
 ]
Out[5]=

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

In[6]:=
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[6]=

See the PlotGridDoc paclet for many additional examples.

Options (33) 

AspectRatio (4) 

Provide a specific aspect ratio for the overall grid:

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],
   Plot[Cos[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True]
   }
  },
 Spacings -> Scaled[0.1],
 ItemSize -> {2, 1},
 AspectRatio -> 1
 ]
Out[7]=

Make the bottom left plot have AspectRatioAutomatic, so that the circle is really a circle:

In[8]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True, Epilog -> {Red, Circle[]}],
   Plot[Cos[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True]
   }
  },
 Spacings -> Scaled[0.1],
 AspectRatio -> {2, 1} -> Automatic
 ]
Out[8]=

Use a Frame[] wrapper to specify the target aspect ratio for the plot with the circle, and also specify an overall aspect ratio:

In[9]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True]
   },
  {
   Frame[
    Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True, Epilog -> {Red, Circle[]}],
    AspectRatio -> Automatic
    ],
   Plot[Cos[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True]
   }
  },
 Spacings -> Scaled[0.1],
 AspectRatio -> 1
 ]
Out[9]=

See the PlotGridDoc paclet for many additional examples.

FrameLabel (2) 

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 individual frame axes and also 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 (2) 

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 (3) 

Make the middle row twice as high as the others:

In[14]:=
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[14]=

Size the rows and columns according to the plot ranges:

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

See the PlotGridDoc paclet for many additional examples.

Spacings (3) 

Separate plots by 30 printer points:

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

Only insert space between rows:

In[17]:=
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[17]=

See the PlotGridDoc paclet for many additional examples.

PlotRange (3) 

With the default setting PlotRangeInherited, the plot ranges of the plots are left unmodified:

In[18]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[2 Sin[x], {x, -2 \[Pi], 2 \[Pi]}, Frame -> True]
   },
  {
   Plot[1.5 Cos[x], {x, -2 \[Pi], 2 \[Pi]}, Frame -> True],
   Plot[Sin[x], {x, -0 \[Pi], 3 \[Pi]}, Frame -> True]
   }
  }
 ]
Out[18]=

Ensure that the plot ranges of the plots are consistent while showing all data:

In[19]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[2 Sin[x], {x, -2 \[Pi], 2 \[Pi]}, Frame -> True]
   },
  {
   Plot[1.5 Cos[x], {x, -2 \[Pi], 2 \[Pi]}, Frame -> True],
   Plot[Sin[x], {x, -0 \[Pi], 3 \[Pi]}, Frame -> True]
   }
  },
 PlotRange -> Max
 ]
Out[19]=

See the PlotGridDoc paclet for a large amount of additional examples.

PlotLabels (4) 

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

In[20]:=
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 -> 35,
 PlotLabels -> Automatic -> "a)"
 ]
Out[20]=

Place the labels outside the plots and number rows first:

In[21]:=
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 -> 35,
 PlotLabels -> Placed[Row -> "i)", {Left, Above}]
 ]
Out[21]=

Add an additional custom label to one of the plots using a Labeled wrapper and modify the style using LabelStyle:

In[22]:=
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 -> 35,
 PlotLabels -> Placed[Row -> "i)", {Left, Above}],
 LabelStyle -> Black
 ]
Out[22]=

See the PlotGridDoc paclet for many additional examples.

LabelingFunction (2) 

Put frames around the labels:

In[23]:=
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[{"Label 1.1", "Label 1.2"}, {Left, Above}],
   Placed[{"Label 2.1", "Label 2.2"}, {After, Center}],
   "Label 3"
   },
 LabelingFunction -> (Framed[Column@#, Background -> White] &)
 ]
Out[23]=

See the PlotGridDoc paclet for many additional examples.

Prolog & Epilog (2) 

Positions inside Prolog and Epilog can be of the form {i,j}pos to specify positions relative to the plot with index {i,j}:

In[24]:=
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 -> 35,
 Epilog -> {
   Blue, Text["A label", {1, 2} -> {2, 0.4}],
   Red, Arrow@{{1, 1} -> {\[Pi]/2, 1}, {2, 1} -> {1, Sin[1]^2}}
   }
 ]
Out[24]=

Positions can also be of type Scaled[], ImageScaled[] and Offset[]:

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 -> 35,
 Epilog -> {
   EdgeForm@Black, FaceForm@None, Rectangle[{1, 1} -> ImageScaled@{0, 0}, {1, 2} -> ImageScaled@{1, 1}],
   Red, Arrow@{{1, 1} -> Scaled@{1, 0}, {2, 1} -> {1, Sin[1]^2}},
   Green, Circle[{2, 1} -> Offset[{10, -10}, Scaled@{0, 1}], Offset[10]]
   }
 ]
Out[25]=

ShowFrameLabels (3) 

Hide all labels unless there is no adjacent plot:

In[26]:=
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[26]=

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

In[27]:=
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[27]=

See the PlotGridDoc paclet for many additional examples.

HideOuterTickLabels (2) 

The option "HideOuterTickLabels" controls how frame ticks should be hidden in order to avoid overlap. While the default is to only hide the outermost tick labels on the left/bottom plot, one can also hide the labels on both plots:

In[28]:=
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[28]=

See the PlotGridDoc paclet for many additional examples.

MergeAxes (2) 

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

In[29]:=
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[29]=

See the PlotGridDoc paclet for many additional examples.

PerformanceGoal (1) 

Setting PerformanceGoal to "Speed" can considerably improve the performance when resizing the plot grid:

In[30]:=
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[30]=

Method

See the PlotGridDoc paclet for many examples.

Possible Issues

See the PlotGridDoc paclet for many examples.

Neat Examples (2) 

Use PlotGrid to create new types of compound plots:

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

Create the plot on the overview page of the PlotGridDoc paclet:

In[33]:=
SeedRandom[1];
data1 = Accumulate /@ RandomReal[{-1, 1}, {2, 100}];
data2 = {
   RandomVariate[NormalDistribution[0, 1], 500],
   RandomVariate[NormalDistribution[3, 1/2], 500]
   };
func3 = Table[BesselJ[n, x], {n, 5}];
ResourceFunction["PlotGrid"][
 {{
   ListLinePlot[
    data1,
    Sequence[
    Frame -> True, PlotTheme -> "VibrantColors", Filling -> Bottom, DataRange -> {0, 10}, BaseStyle -> {FontSize -> 15}, FrameStyle -> Black]
    ],
   Histogram[
    data2,
    Sequence[
    Frame -> True, PlotTheme -> "VibrantColors", BaseStyle -> {FontSize -> 15}, FrameStyle -> Black]
    ]
   },
  {
   Plot[
    Evaluate@func3,
    {x, 0, 10},
    Sequence[
    Frame -> True, PlotTheme -> "VibrantColors", BaseStyle -> {FontSize -> 15}, FrameStyle -> Black]
    ], SpanFromAbove}},
 Spacings -> {35, 10},
 "ShowFrameLabels" -> {{Automatic}, {Full}},
 PlotLabels -> Automatic -> Style["a)", Large, Black],
 ItemSize -> {{2, 1}, 1.59},
 ImageSize -> 590,
 Epilog -> {Black, Thick, Arrow@{{1, 1} -> {8.9, data1[[2, 89]]}, {2, 1} -> Block[{x = Pi}, {x, func3[[2]]}]}}
 ]
Out[34]=

Publisher

Lukas Lang

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 4.4.1 – 30 September 2024
  • 4.4.0 – 12 July 2023
  • 4.3.3 – 24 April 2023
  • 4.3.2 – 23 December 2022
  • 4.3.1 – 27 September 2022
  • 4.3.0 – 21 July 2022
  • 3.0.0 – 03 September 2020
  • 2.0.0 – 12 June 2020
  • 1.0.0 – 15 October 2019

Related Resources

Author Notes

Changes from version 4.4.0 to 4.4.1:

Fix an issue when normalizing ticks with length Automatic, as e.g. generated by DateListPlot.
Move many of the examples into a separate PlotGridDoc paclet.

Changes from version 4.3.3 to 4.4.0:

Added ability to apply custom styles to merge indicators via Style[spec,style1,] type wrappers.
Improved the look of merge indicators by removing clipping at the edge between the two halves. This will require updates to the PlotRange settings of fully custom merge indicators (the plot range in the direction of the length of the indicator will need to be multiplied by 2).

Changes from version 4.3.2 to 4.3.3:

Resolved an issue where the generated plots could not be exported as PDFs in versions 13.2 and above.

Changes from version 4.3.1 to 4.3.2:

Resolved an issue that resulted in clipped tick labels when large fonts and small plot sizes were used.
Added a warning message when zero-sizes merge indicators are generated.
Resolved an issue with PlotRange settings containing All and Automatic not working.

Changes from version 4.3.0 to 4.3.1:

Resolved an issue where the generated plots could not be exported as PDFs. (This is a workaround for a bug in Export)

Changes from version 4.2.0 to 4.3.0:

Fixed front-end crash in 12.3 by disabling the "Get Coordinates" tool in that version
Fixed PlotGrid not working when invoked from wolframscript or in the cloud
Fixed "FixFrameTicks"True not working properly in 13.0 due to a partial fix of the underlying issue
Added extended AspectRatio specifications to target AspectRatio settings for individual plots
Added extended coordinate specification to Prolog and Epilog, enabling the easy creation of inter-plot annotations.
Reduced clipping of frame borders due to rounding/aliasing issues

Changes from version 4.1.0 to 4.2.0:

Remove floating loops of merge indicators produced e.g. by merging the axes of a 2x2 grid of plots
Fixed merge indicators not being properly suppressed if the relevant part of the frame is hidden

Changes from version 4.0.0 to 4.1.0:

Fixed issues with certain labels specifications being corrupted (e.g. the top frame of a DateListPlot)

Changes from version 3.0.0 to 4.0.0:

Fixed issues with ImagePadding when using non-default PlotRange settings

Changes from version 2.0.0 to 3.0.0:

Added PlotRange option to enable automatically consistent plot ranges.
Improved quality of resulting plots by ensuring that modified ticks are not cut off by wrong ImagePadding

Changes from version 1.3.0 to 2.0.0:

Fixed ticks of legended plots not displaying properly in fresh kernel sessions

Changes from version 1.2.0 to 1.3.0:

Changed tiebreaking for label combining to favor rows over columns
Added support for Placed wrappers around lists of labels
Added support for several top-level label list specs
Added LabelingFunction option
Fixed issues with automatic WindowSize settings for the notebook—thanks to Richard Hennigan (Wolfram Research) for finding and diagnosing this!

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