Wolfram Research

Function Repository Resource:

PlotGrid

Source Notebook

Create stacked plots and other advanced grid layouts of plots

Contributed by: Lukas Lang  |  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 positoning, 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/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:
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
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.
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 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]=

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

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

AspectRatio (8) 

With the default setting AspectRatio->Automatic, the aspect ratio of the resulting grid is based on a combination of the ItemSize setting and the AspectRatio settings of the individual plots:

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

Changing the AspectRatio of the plots changes the resulting aspect ratio:

In[11]:=
ResourceFunction["PlotGrid"][
 {
  {
   Plot[Sin[x], {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x], {x, -\[Pi], \[Pi]}, Frame -> True, AspectRatio -> 3]
   },
  {
   Plot[Sin[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True],
   Plot[Cos[x]^2, {x, -\[Pi], \[Pi]}, Frame -> True]
   }
  },
 Spacings -> Scaled[0.1]
 ]
Out[11]=

Changing the ItemSize setting affects the aspect ratio:

In[12]:=
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}
 ]
Out[12]=

Base the aspect ratio only on the aspect ratios of the individual plots:

In[13]:=
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 -> GeometricMean
 ]
Out[13]=

Target a specific aspect ratio:

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

Make it so the bottom left plot effectively has AspectRatio->Automatic, so that the circle is really a circle:

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

Trying to make all plots have AspectRatio->Automatic is not always possible:

In[16]:=
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 -> All -> Automatic
 ]
Out[16]=

Equalizing the PlotRange settings will usually resolve the problem:

In[17]:=
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 -> All -> Automatic,
 PlotRange -> Max
 ]
Out[17]=

Another possibility is to only apply the aspect ratio target to as many plots as possible:

In[18]:=
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 -> Automatic -> Automatic
 ]
Out[18]=

Only rows/columns with ItemSize set to Automatic will be resized to hit the aspect ratio targets:

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

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

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

Use a mixture of different target aspect ratios and specify the overall aspect ratio of the grid:

In[21]:=
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 -> {1, {1, 1} -> Inherited, {2, 2} -> GoldenRatio}
 ]
Out[21]=

FrameLabel (2) 

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

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

Label both individual frame axes and the whole group:

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

FrameStyle (2) 

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

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

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

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

ItemSize (5) 

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

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

Make the middle row twice as high:

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

Size the rows and columns according to the plot ranges:

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

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

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

Make the first row and column 100 printers points big:

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

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

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

Spacings (5) 

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

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

Separate plots by 30 printers points:

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

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

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

Only insert space between rows:

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

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

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

PlotRange (5) 

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

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

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

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

Use a reduced plot range to ensure all plots are filled out:

In[39]:=
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 -> Min
 ]
Out[39]=

Show everything in the vertical range, but crop the horizontal range to the common part of the ranges:

In[40]:=
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 -> {Min, Max}
 ]
Out[40]=

Use explicit settings for the plot ranges, using Directive instead of {…} to prevent ambiguity:

In[41]:=
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 -> {
   {Directive[-3, 2], Directive[2, 6]},
   {Directive[-2.5, 2.5], Directive[-1, 3]}
   }
 ]
Out[41]=

PlotLabels (8) 

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

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

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

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

Apply styling to the labels and use sequential numbers:

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 -> 35,
 PlotLabels -> Automatic -> Style["1.", 20, Black]
 ]
Out[44]=

Place the labels outside the plots and number rows first:

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

The base style of the labels is affected by LabelStyle:

In[46]:=
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}],
 LabelStyle -> {Black, 15}
 ]
Out[46]=

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

In[47]:=
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}]
 ]
Out[47]=

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

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

Number plots automatically, but add an additional description to each plot:

In[49]:=
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 -> "(1)",
    {"Plot 1", "Plot 2", "Plot 3"},
    {{}}(* to avoid ambiguity *)
    },
   {Left, Top}
   ]
 ]
Out[49]=

LabelingFunction (4) 

With the default setting LabelingFunctionAutomatic, labels with the same position are put into a row/column, depending on the position of the labels:

In[50]:=
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}]
   }
 ]
Out[50]=

Stack all labels vertically:

In[51]:=
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}]
   },
 LabelingFunction -> Column
 ]
Out[51]=

Put frames around the labels:

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

Put frames around the labels, but preserve the automatic layout:

In[53]:=
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 -> Automatic -> (Framed[#, Background -> White] &)
 ]
Out[53]=

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

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

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

ShowFrameLabels (6) 

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

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

Labels are shown if a plot is omitted:

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

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

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

Show no frame labels:

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

Show all frame labels:

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

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

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

HideOuterTickLabels (6) 

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[62]:=
ResourceFunction["PlotGrid"][
 Table[
  Graphics[
   Text[{i, j}],
   PlotRange -> {{-j, j}, {-i, i}},
   Frame -> True
   ],
  {i, 3},
  {j, 3}
  ],
 Spacings -> {{None, 30}, {None, 30}}
 ]
Out[62]=

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

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

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

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

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

Do not hide any tick labels, potentially causing overlaps:

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

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

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

MergeAxes (7) 

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

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

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

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

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

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

The frame styles of both plots are inherited:

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

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

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

Use a custom merge indicator:

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

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

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

PerformanceGoal (1) 

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

Method (4) 

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

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

Turning the fix off might yield unexpected results:

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

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

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

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

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

Possible Issues (7) 

PlotGrid assumes that plots have compatible plot ranges:

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

Use the option PlotRange to enforce consistent plot ranges:

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

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

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

Specify the size directly instead:

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

The ticks might sometimes be changed by PlotGrid:

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

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

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

Invalid specifications for spanning plots lead to leftover span indicators:

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

Some label specifications are potentially ambiguous and might be interpreted in an unexpected way:

In[89]:=
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 -> "(1)",
    {"Plot 1", "Plot 2", "Plot 3"}
    },
   {Left, Top}
   ]
 ]
Out[89]=

Add an empty two-level label specification to ensure the specification is interpreted as a list of several top-level label lists:

In[90]:=
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 -> "(1)",
    {"Plot 1", "Plot 2", "Plot 3"},
    {{}}(* to avoid ambiguity *)
    },
   {Left, Top}
   ]
 ]
Out[90]=

Some settings for AspectRatio will lead to unresolvable constraints on the sizes of the rows and columns:

In[91]:=
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],
 AspectRatio -> {{1, 1} -> 2, {1, 2} -> 1, {2, 1} -> 2, {2, 2} -> 0.5}
 ]
Out[91]=

Remove some of the AspectRatio targets:

In[92]:=
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],
 AspectRatio -> {{1, 1} -> 2, {1, 2} -> 1, {2, 2} -> 0.5}
 ]
Out[92]=

Targeting AspectRatio settings for individual plots is not supported when Offset type specifications are used:

In[93]:=
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 -> 35,
 AspectRatio -> {1, 1} -> 2
 ]
Out[93]=

Use Scaled[…] type Spacings instead:

In[94]:=
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],
 AspectRatio -> {1, 1} -> 2
 ]
Out[94]=

Neat Examples (1) 

Use PlotGrid to create new types of compound plots:

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

Resource History

Source Metadata

Related Resources

Author Notes

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