Subplots
Contents
Elements of a plot
Figure and Axes
Before getting into the subplots topic, let us first discuss about the two main elements in a plot – Figure and Axes.
Figure
A Figure object can be thought of as a window on which plots are rendered and it contains all the plotting elements.
Axes
The Axes is the actual plotting area contained within the figure object. There can be multiple axes objects in a figure object. The Axes contains the x-axis,y-axis,data points,lines,ticks,text etc.,


Interfaces
The Matplotlib library provides two important interfaces for rendering plots:
1. State-machine interface
2. Object Oriented interface
What is a state-machine?
A finite state machine is an abstract concept wherein a system can exist in a finite number of states. But at any given point of time, it can be in exactly one of these states. Depending on the operations performed on the state machine, it can change from one state to another.
State-machine interface
The figure on which plots are rendered behaves like a state-machine system. The state-machine interface keeps track of the current figure, axes and the current state of the figure and hence is called stateful interface. The state-machine interface makes calls to various methods using the pyplot module and it is also known as Pyplot interface. When a method is called using the pyplot module, a figure and axes objects are created implicitly and changes are made to the figure, hence changing the state of the figure. We do not define any objects or variables when using this interface. We simply call methods defined in the pyplot module and the changes appear in the figure.
The pyplot interface is useful to render simple plots with minimum code or for quickly testing our code, because we can issue a command and immediately see the result. But if we are working on multiple plots it becomes difficult to keep track of the active figure and the plots.
Object-oriented interface
Matplotlib also supports the object oriented interface or the stateless interface. This interface is called stateless because instead of creating a global figure instance, a figure object is created and referenced with a variable. We can then directly call methods on this variable to change the different elements in a plot. Because we are storing a reference to the plotting objects in variables, it is easy to track the objects that we are working on. The object-oriented interface is a more pythonic and recommended way to use Matplotlib.
The pyplot interface is infact built on top of the object-oriented interface. The top layer is the front-end interface that is used by users without much programming experience to test simple plots. Calling methods such as line,scatter,bar,hist etc., from pyplot module, creates a figure instance implicitly and generates the respective plots. The bottom layer can be used to develop complicated visualizations as it provides more control and allows for customization of the plots.
A figure object can be created using pyplot. In the object oriented interface as well, pyplot is used to create the figure and the axes objects. In order to render the plots, we then call the various methods directly on these objects.
Subplots
Subplot method
Up until now, we have seen various plots such as line plots, bar charts, pie charts, scatter plots etc., In many examples we have generated one plot on one figure, we have also seen examples where we generated multiple plots on one figure. What if you are required to have plots side by side or one plot on top of the other in a figure? This can be achieved with subplots. A subplot is a plot that takes up only a part of the figure object. In Matplotlib,a subplot is also referred to as an axes. We will now see how to generate subplots using the object oriented approach.
The subplot method is used to divide a figure into multiple subplots: subplot (m, n, index, kwargs)**
The subplot method returns an axes object and is used to divide a figure into a matrix of m rows and n columns, creating m*n subplots in one figure. The index number provides the location of the current axes for plotting. The index number starts from 1 and the subplots are numbered from left to right beginning from the first row upto the mth row.
from matplotlib import pyplot as plt
import numpy as np
fig1 = plt.figure(num=1,figsize=(10,6))
ax1 = plt.subplot(111)
x = np.arange(1,10)
y = np.arange(1,10)
ax1.plot(x,y,color='c',marker='p')
plt.title('Subplot_1')
plt.show()

Subplots method
In order to plot using the subplot function, the given subplot has to be first set as the current/active axes for plotting by specifying the index number and this becomes tedious if there are too many subplots. Matplotlib also provides the subplots method which returns a figure object and a numpy array of axes objects.
subplots(m=1, n=1, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, fig_kw)**
fig2, ax = plt.subplots(2,1,sharex='col')
x = np.arange(1,11)
y = np.arange(1,11)
z = np.random.randn(10)
# Subplot1
ax[0].plot(x,y,color='g',marker='p',label='axes1')
ax[0].set_title('Axes1')
# Subplot2
ax[1].plot(x,z,marker='o',label='axes2')
ax[1].set_title('Axes2')
plt.tight_layout()
plt.show()

fig2, ax = plt.subplots(2,2,sharex='col',sharey='row')
x = np.arange(1,11)
y = np.arange(1,11)
z = np.random.randn(10)
#Subplot1
ax[0][0].plot(x,y,color='g',marker='p',label='axes1')
ax[0][0].set_title('Axes1')
ax[0][0].legend()
#Subplot2
ax[0][1].scatter(x,y,color='k',marker='^',label='axes2')
ax[0][1].set_title('Axes2')
ax[0][1].legend()
#Subplot3
ax[1][0].plot(x,z,marker='v',label='axes3')
ax[1][0].set_title('Axes3')
ax[1][0].legend()
#Subplot4
ax[1][1].scatter(x,z,marker='o',label='axes4')
ax[1][1].set_title('Axes4')
ax[1][1].legend()
plt.tight_layout()
plt.show()

Add axes method
You can also specify the position and the dimensions of an axes using the add_axes method.
add_axes([left, bottom, width, height])
A list is passed to this method containing the elements:
- left, bottom (coordinates of lower left corner of the axes).
- width, height of the axes object.
The values for all the 4 parameters range in between 0 and 1, representing the fraction of the figure that the axes occupies.
fig3 = plt.figure()
ax3 = fig3.add_axes([0.1,0.1,0.8,0.8])
inset_ax = fig3.add_axes([0.15,.6,0.2,0.2])
ax3.plot(x,y)
inset_ax.plot(x,y)
plt.show()

In the above example, we have a subplot enclosed in another subplot.