This page is obsolete, I wrote it while I was just starting to learn python. I have wrote a much better set of notes on pandas available here:
Table of contents
Prequisites
Data
Let's recreate the dataframe which we looked at then we looked at bar graphs.
We can view the rainfalldf dataframe in variable explorer:

As we can see, this gives the rainfall per month up until May 2019.

Creating a Plot (Simple Bar Graph)

Tight Layout
As we can see, the bottom of the xlabel is cut from the plot. This can be solved by using the tight layout.

Assigning a Figure, Axes and Plot to Variables
Let's have a look at recreating the plot above but in this case we will go through it step by step and assign the figure, axes and plot to variable names.
Figure
We close all plots (line 24) and then create figure(1) using the command figure (line 25) which creates a blank figure canvas. This blank canvas can be assigned to a variable, in this case fig1 which we can later access.

We can now have a look at the properties of the figure using getp in the command window
agg_filter = None
alpha = None
animated = False
axes = []
children = [<matplotlib.patches.Rectangle object at 0x0000022...
clip_box = None
clip_on = True
clip_path = None
constrained_layout = False
constrained_layout_pads = (0.04167, 0.04167, 0.02, 0.02)
contains = None
default_bbox_extra_artists = []
dpi = 100.0
edgecolor = (1.0, 1.0, 1.0, 1.0)
facecolor = (1.0, 1.0, 1.0, 1.0)
figheight = 4.8
figure = None
figwidth = 6.4
frameon = True
gid = None
in_layout = True
label =
path_effects = []
picker = None
rasterized = None
size_inches = [6.4 4.8]
sketch_params = None
snap = None
tight_layout = False
transform = IdentityTransform()
transformed_clip_path_and_affine = (None, None)
url = None
visible = True
window_extent = TransformedBbox( Bbox(x0=0.0, y0=0.0, x1=6.4, ...
zorder = 0
Axes
As we can see the axes are empty. We can then select this plot and add a set of axes to it (line 27) and save these axes to a variable ax1. For example by adding a single subplot which occupies the figure.

Note the first digit m=1 corresponds to the number of rows of subplots, the second digit n=1 corresponds to the number of columns of subplots and the third digit o=1 selects the subplot to plot from. The number of subplots ranges from 1 to m×n in this case 1×1. Note zero order indexing does not apply here.

This gives a default single plot which has an axes which covers the 1st and only subplot occupying the figure canvas. As no data is present in the axes, the default axes limits in x and y will be [0,1]. These will rescale to suit data, when data is plotted. We can get the properties of the axes from the command line
adjustable = box
agg_filter = None
alpha = None
anchor = C
animated = False
aspect = auto
autoscale_on = True
autoscalex_on = True
autoscaley_on = True
axes_locator = None
axisbelow = line
children = [<matplotlib.spines.Spine object at 0x0000022DA29D...
clip_box = None
clip_on = True
clip_path = None
contains = None
data_ratio = 1.0
default_bbox_extra_artists = [<matplotlib.spines.Spine object at 0x0000022DA29D...
facecolor = (1.0, 1.0, 1.0, 1.0)
fc = (1.0, 1.0, 1.0, 1.0)
figure = Figure(640x480)
frame_on = True
geometry = (1, 1, 1)
gid = None
gridspec = GridSpec(1, 1)
images = <a list of 0 AxesImage objects>
in_layout = True
label =
legend = None
legend_handles_labels = ([], [])
lines = <a list of 0 Line2D objects>
navigate = True
navigate_mode = None
path_effects = []
picker = None
position = Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=...
rasterization_zorder = None
rasterized = None
renderer_cache = None
shared_x_axes = <matplotlib.cbook.Grouper object at 0x0000022D9E98...
shared_y_axes = <matplotlib.cbook.Grouper object at 0x0000022D9E9C...
sketch_params = None
snap = None
subplotspec = <matplotlib.gridspec.SubplotSpec object at 0x00000...
title =
transform = IdentityTransform()
transformed_clip_path_and_affine = (None, None)
url = None
visible = True
window_extent = Bbox(x0=76.5, y0=49.3, x1=579.5, y1=425.9)
xaxis = XAxis(80.000000,52.800000)
xaxis_transform = BlendedGenericTransform( CompositeGenericTrans...
xbound = (0.0, 1.0)
xgridlines = <a list of 6 Line2D xgridline objects>
xlabel =
xlim = (0.0, 1.0)
xmajorticklabels = <a list of 6 Text xticklabel objects>
xminorticklabels = <a list of 0 Text xticklabel objects>
xscale = linear
xticklabels = <a list of 6 Text xticklabel objects>
xticklines = <a list of 12 Line2D xtickline objects>
xticks = [0. 0.2 0.4 0.6 0.8 1. ]
yaxis = YAxis(80.000000,52.800000)
yaxis_transform = BlendedGenericTransform( BboxTransformTo( ...
ybound = (0.0, 1.0)
ygridlines = <a list of 6 Line2D ygridline objects>
ylabel =
ylim = (0.0, 1.0)
ymajorticklabels = <a list of 6 Text yticklabel objects>
yminorticklabels = <a list of 0 Text yticklabel objects>
yscale = linear
yticklabels = <a list of 6 Text yticklabel objects>
yticklines = <a list of 12 Line2D ytickline objects>
yticks = [0. 0.2 0.4 0.6 0.8 1. ]
zorder = 0
Since we have just created a single subplot, using the command plt.axes will give the same result.

Once again we can look at the axes properties using the command line:
adjustable = box
agg_filter = None
alpha = None
anchor = C
animated = False
aspect = auto
autoscale_on = True
autoscalex_on = True
autoscaley_on = True
axes_locator = None
axisbelow = line
children = [<matplotlib.spines.Spine object at 0x000001EEB5F0...
clip_box = None
clip_on = True
clip_path = None
contains = None
data_ratio = 1.0
default_bbox_extra_artists = [<matplotlib.spines.Spine object at 0x000001EEB5F0...
facecolor = (1.0, 1.0, 1.0, 1.0)
fc = (1.0, 1.0, 1.0, 1.0)
figure = Figure(640x480)
frame_on = True
geometry = (1, 1, 1)
gid = None
gridspec = GridSpec(1, 1)
images = <a list of 0 AxesImage objects>
in_layout = True
label =
legend = None
legend_handles_labels = ([], [])
lines = <a list of 0 Line2D objects>
navigate = True
navigate_mode = None
path_effects = []
picker = None
position = Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=...
rasterization_zorder = None
rasterized = None
renderer_cache = None
shared_x_axes = <matplotlib.cbook.Grouper object at 0x000001EEB38D...
shared_y_axes = <matplotlib.cbook.Grouper object at 0x000001EEB391...
sketch_params = None
snap = None
subplotspec = <matplotlib.gridspec.SubplotSpec object at 0x00000...
title =
transform = IdentityTransform()
transformed_clip_path_and_affine = (None, None)
url = None
visible = True
window_extent = Bbox(x0=76.5, y0=49.3, x1=579.5, y1=425.9)
xaxis = XAxis(80.000000,52.800000)
xaxis_transform = BlendedGenericTransform( CompositeGenericTrans...
xbound = (0.0, 1.0)
xgridlines = <a list of 6 Line2D xgridline objects>
xlabel =
xlim = (0.0, 1.0)
xmajorticklabels = <a list of 6 Text xticklabel objects>
xminorticklabels = <a list of 0 Text xticklabel objects>
xscale = linear
xticklabels = <a list of 6 Text xticklabel objects>
xticklines = <a list of 12 Line2D xtickline objects>
xticks = [0. 0.2 0.4 0.6 0.8 1. ]
yaxis = YAxis(80.000000,52.800000)
yaxis_transform = BlendedGenericTransform( BboxTransformTo( ...
ybound = (0.0, 1.0)
ygridlines = <a list of 6 Line2D ygridline objects>
ylabel =
ylim = (0.0, 1.0)
ymajorticklabels = <a list of 6 Text yticklabel objects>
yminorticklabels = <a list of 0 Text yticklabel objects>
yscale = linear
yticklabels = <a list of 6 Text yticklabel objects>
yticklines = <a list of 12 Line2D ytickline objects>
yticks = [0. 0.2 0.4 0.6 0.8 1. ]
zorder = 0
Figure and Axes Combined
Line 25 and 27 can be combined to a single line using the command subplots. Here two output arguments are defined fig1 and ax1

fig1=
agg_filter = None
alpha = None
animated = False
axes = [<matplotlib.axes._subplots.AxesSubplot object at ...
children = [<matplotlib.patches.Rectangle object at 0x0000020...
clip_box = None
clip_on = True
clip_path = None
constrained_layout = False
constrained_layout_pads = (0.04167, 0.04167, 0.02, 0.02)
contains = None
default_bbox_extra_artists = [<matplotlib.axes._subplots.AxesSubplot object at ...
dpi = 100.0
edgecolor = (1.0, 1.0, 1.0, 1.0)
facecolor = (1.0, 1.0, 1.0, 1.0)
figheight = 4.8
figure = None
figwidth = 6.4
frameon = True
gid = None
in_layout = True
label =
path_effects = []
picker = None
rasterized = None
size_inches = [6.4 4.8]
sketch_params = None
snap = None
tight_layout = False
transform = IdentityTransform()
transformed_clip_path_and_affine = (None, None)
url = None
visible = True
window_extent = TransformedBbox( Bbox(x0=0.0, y0=0.0, x1=6.4, ...
zorder = 0
ax1=
adjustable = box
agg_filter = None
alpha = None
anchor = C
animated = False
aspect = auto
autoscale_on = True
autoscalex_on = True
autoscaley_on = True
axes_locator = None
axisbelow = line
children = [<matplotlib.spines.Spine object at 0x000002090B35...
clip_box = None
clip_on = True
clip_path = None
contains = None
data_ratio = 1.0
default_bbox_extra_artists = [<matplotlib.spines.Spine object at 0x000002090B35...
facecolor = (1.0, 1.0, 1.0, 1.0)
fc = (1.0, 1.0, 1.0, 1.0)
figure = Figure(640x480)
frame_on = True
geometry = (1, 1, 1)
gid = None
gridspec = GridSpec(1, 1)
images = <a list of 0 AxesImage objects>
in_layout = True
label =
legend = None
legend_handles_labels = ([], [])
lines = <a list of 0 Line2D objects>
navigate = True
navigate_mode = None
path_effects = []
picker = None
position = Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=...
rasterization_zorder = None
rasterized = None
renderer_cache = None
shared_x_axes = <matplotlib.cbook.Grouper object at 0x0000020904D7...
shared_y_axes = <matplotlib.cbook.Grouper object at 0x0000020904DC...
sketch_params = None
snap = None
subplotspec = <matplotlib.gridspec.SubplotSpec object at 0x00000...
title =
transform = IdentityTransform()
transformed_clip_path_and_affine = (None, None)
url = None
visible = True
window_extent = TransformedBbox( Bbox(x0=0.125, y0=0.109999999...
xaxis = XAxis(80.000000,52.800000)
xaxis_transform = BlendedGenericTransform( CompositeGenericTrans...
xbound = (0.0, 1.0)
xgridlines = <a list of 6 Line2D xgridline objects>
xlabel =
xlim = (0.0, 1.0)
xmajorticklabels = <a list of 6 Text xticklabel objects>
xminorticklabels = <a list of 0 Text xticklabel objects>
xscale = linear
xticklabels = <a list of 6 Text xticklabel objects>
xticklines = <a list of 12 Line2D xtickline objects>
xticks = [0. 0.2 0.4 0.6 0.8 1. ]
yaxis = YAxis(80.000000,52.800000)
yaxis_transform = BlendedGenericTransform( BboxTransformTo( ...
ybound = (0.0, 1.0)
ygridlines = <a list of 6 Line2D ygridline objects>
ylabel =
ylim = (0.0, 1.0)
ymajorticklabels = <a list of 6 Text yticklabel objects>
yminorticklabels = <a list of 0 Text yticklabel objects>
yscale = linear
yticklabels = <a list of 6 Text yticklabel objects>
yticklines = <a list of 12 Line2D ytickline objects>
yticks = [0. 0.2 0.4 0.6 0.8 1. ]
zorder = 0
Finally leaving the input arguments blank in line 26 will default to nrow=1, ncol=1 and num=1.

Plot
Now the plot can be assigned to the axes.

We can also look up the properties of plot1
agg_filter = None
alpha = None
animated = False
antialiased or aa = True
bbox = Bbox(x0=-0.4, y0=0.0, x1=0.4, y1=215.6)
capstyle = butt
children = []
clip_box = TransformedBbox( Bbox(x0=0.0, y0=0.0, x1=1.0, ...
clip_on = True
clip_path = None
contains = None
data_transform = CompositeGenericTransform( TransformWrapper( ...
edgecolor or ec = (0.0, 0.0, 0.0, 1.0)
extents = Bbox(x0=95.969696969697, y0=74.28416860022952, x1=...
facecolor or fc = (0.0, 0.6901960784313725, 0.3137254901960784, 0.8)
figure = Figure(640x478)
fill = True
gid = None
hatch = O
height = 215.6
in_layout = True
joinstyle = miter
label = _nolegend_
linestyle or ls = solid
linewidth or lw = 1.2
patch_transform = CompositeGenericTransform( BboxTransformTo( ...
path = Path(array([[0., 0.], [1., 0.], [1.,...
path_effects = []
picker = None
rasterized = None
sketch_params = None
snap = None
transform = CompositeGenericTransform( CompositeGenericTra...
transformed_clip_path_and_affine = (None, None)
url = None
verts = [[ 95.96969697 74.2841686 ] [130.12823147 74.28...
visible = True
width = 0.8
window_extent = Bbox(x0=95.969696969697, y0=74.28416860022952, x1=...
x = -0.4
xy = (-0.4, 0)
y = 0
zorder = 1
Setting XTicks and XLabels
In the past we used the command which set the xticks for the currently selected axes.
However it is also possible to explicitly select the axes and alter the xticks of the axes. For example if in the console we type in ax1. then tab we will get a list of commands we can index into ax1. Many of the commands will begin with get which can be used to view current properties and set which can be used to set new properties.

Note the input arguments for plt.xticks and ax1.set_xticks are slightly different with ax1.set_xticks being more restrictive and requiring the additional use of ax1.set_xticklabels to get all the options presented in plt.xticks.
Before ax1 xticks are set, the xticks are equally spaced from 0 to 12 in steps of 2.

We can set them to be equally spaced from 0 to 12 in steps of 1 (line 31).


Setting Axes Titles
Likewise the xlabel, ylabel and title can be set using the same convention.

Legend
The legend can also be added by indexing into ax1.

Grid
The grid can also be added by indexing into ax1.

Tight Layout
The tight layout is assigned to the figure and not the axes. It can be assigned to the figure by indexing into fig1

The steps above hae reproduced the figure above but have assigned the figure, axes and plot to fig1, ax1 and plot1 respectively and the properties of the zxes have been altered mainly by use of indexing into ax1 opposed to using plt which indexes into the currently selected axes. In this case, since we only have one set of axes it appears to yield the same result however some of these commands are required for plots with more complicated axes types which we will look at next and some of these commands are required when looking at 3D plots.
Moving Y-Axes to the Right
To move the y-axes to the right we have to index into ax1 and select the yaxis and then set the location to the right (line 35)

In this case, the label still remains on the left, we may also wish to move this to the right by setting the label position (line 36):

Moving X Axes to the Top
We can likewise move the x-axes to the top (line 38 and 39)

Two Y-Axes
In some case, one may want two different y-axes for a dataset for example if one wants to display the same set of data using two different measurement systems. This can be done by creating a second set of axes from ax1 using the function twinx (line 35).

Because no data is added to these second axes, they will range between the default values of 0 and 1. Data can be added to these axes by creating another plot and the axes will automatically adjust. However in this case, we want the right axes to relate to the original data, displaying it in inches instead of mm.
To do this we can index into ax1 and get the ylimits (line 39) saving the lower and upper bound to variables. We can then index into ax2 and set the ylimits to match these lower and upper bounds divided by the scaling factor 2.54 to get the limits in inches (line 41) and create a new ylabel for these second axes (line 42).

Two X-Axes and Two Y-Axes
An additional top x-axis can be made likewise by using the function twiny (lines 47-55). In this case we can show the value of the numeric months at the top and show the 3 letter abbreviations at the bottom x-axis.

Creating a Plot with SubPlots
Now let's have a look at the use of subplots.
2 by 1 Subplots
Say we want instead of a single subplot, a figure with 2 subplots (2 rows and 1 column). We can use the code above and modify line 27 for 2 subplots. On the left side we must designate the output arguments, the 0th output argument will be the figure as before. The 1st order argument will be an array of axes. In our case we can call these ax1 and ax2. Our naming convention will use 1st order indexing opposed to 0th order indexing as subplots are named in accordance to 1st order indexing. Here we set the nrows=2, ncols=1 and for the third input argument we can set num=1 (subplot1 corresponding to ax1). We could also set num=2 (subplot2 corresponding to ax2) for the third input argument. The third argument will just designate the current axes selected (for instance if one uses the plt command).

We can now carry out a plot. Let's have a look at:

We could also select ax2

Or alternatively create a plot with two bar graphs for example, 2016 data and 2017 data.

Once again we can change the properties of ax1.

And we can do the same for ax2.

2 by 2 Subplots
We can create more complicated subplots such as a 2 rows by 2 columns subplot.

We can select any of the four axes to plot to:




We can create a plot of 2016, 2017, 2018 and 2019 rainfall using these four subplots:

Height and Width ratios
It is also possible to use gridspec and then to use height_ratios and/or width_ratios to make some subplots larger than others.

Grid Specification
Sometimes we may wish to create subplots of different sizes. For example a figure with 3 plots and we may wish for the third subplot to occupy the space of the 3rd and 4th subplot i.e. be twice as wide as subplot1 and subplot2. This is done by using gridspec (line 27). In this case the gridspec is set to a 2 by 2 matrix. Each subplot is created by using the command add_subplot with an input argument indexing into the created gridspec and then assigned to a axes variable. Note indexing into the gridspec, gs1 uses 0 order indexing. Since the third subplot is plotted across all columns, we use the semicolon.
