Matplotlib Guide - p1
Plotting data with matplotlib
What is Matplotlib?
Matplotlib is a plotting library for the Python programming language and its numerical mathematics extension, NumPy. Matplotlib is a powerful and widely used library that provides an object-oriented API for embedding plots into applications using general-purpose GUI toolkits like Tkinter, wxPython, Qt, or GTK+.
This Notebook covers following topics:
- Plot charts, individually and in multiples.
- Set the Tick, Text, Legend, and Annotate elements of a plot.
- Customize the Grid and Spine displays of a plot.
- Set the colors for different elements of a plot
- Customize the style and appearance of different plot components.
- Choose different chart types based on data type and requirement.
- Show the distribution of data.
- Show the relationship between different variables.
- Plot data in 2D and 3D.
Anotomy of matplotlib
Figure
The whole Figure, which is marked by the red box, is like a canvas. Everything that we want to draw will be on this canvas. The figure can contain one or more axes plots. Regardless of how many we draw, the figure controls all of the axes.
Axes
The axes are marked by the blue box. They are where the data will appear. While one figure can contain more than one axes, the axes can only belong to one figure.
Axis
The x-axis and the y-axis, both circled in green, are number-line-like objects. They set the graph limits and generate the ticks (the marks on the axis) and the tick labels (the strings labeling the ticks).
Artist
Artist is the collection of objects that know how to use a renderer to paint the canvas or figure. Artist encompasses many objects, such as the title, legend, axis, spine, grid, and tick
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
%matplotlib inline
points = np.linspace(-5,5,256)
y1 = np.tanh(points) + 0.5
y2 = np.sin(points) - 0.2
# 2. Create canvas/figure
fig,ax = plt.subplots(1,1,figsize=(15,9))
# 3. Add data to axes (x,y)
ax.hlines(0,-6,6)
ax.plot(points,y1,label="tanh")
ax.plot(points,y2,color="green",marker='.',linestyle='dashed',label="sin")
# 4. Show the figure
plt.show()
# To save the image use following lines
# fig.savefig('output/to.png')
# plt.close(fig)
What are ticks?
Ticks are the marks on the x and y axis of the plot. The tick can be a number, a string, or any other notation. When plotting a graph, the axes will set a default tick based on the number ranges of the different axes.
The following are some properties that we can manipulate by setting parameters:
- which: Sets the x/y major/minor ticks. The default value is major.
- color: Sets the tick color.
- labelrotation: Rotates the tick label.
- width: Sets the tick width in points.
- length: Sets the tick length in points.
- direction: Sets the direction of the ticks, either towards the axis or away from it. The default value is out.
points = np.linspace(-5, 5, 256)
y1 = np.tanh(points) + 0.5
y2 = np.sin(points) - 0.2
fig,ax = plt.subplots(dpi=600,figsize=(15,9))
ax.plot(points,y1)
ax.plot(points,y2)
# Set x Tick
ax.set_xticks(np.linspace(-5,5,9))
plt.show()
points = np.linspace(-5, 5, 256)
y1 = np.tanh(points) + 0.5
y2 = np.sin(points) - 0.2
fig,ax = plt.subplots(nrows=1,ncols=2,dpi=400,figsize=(10,6))
ax[0].plot(points,y1)
ax[0].plot(points,y2)
ax[0].set_title("Original")
ax[1].plot(points,y1)
ax[1].plot(points,y2)
ax[1].set_title("Pretty")
ax[1].set_xticks(np.linspace(-5,5,9))
ax[1].tick_params(color='b',length=5, width=2,direction='in')
plt.show()
What is the spine?
Spines are lines that connect the axis tick marks to one another. Spines also note the boundaries of the data area. They can be placed in any position we want. By default, they are the boundary of the entire axes. So, for an axes, we have four spines:
- top
- bottom
- left
- right
set_position()
accepts a tuple of (position type, amount) as parameter. The position type has the following types.
-
axes
: places the spine at the specified axes coordinate (from 0.0-1.0) -
data
: places the spine at the specified data coordinate. -
outward
: places the spine out from the data area by the specified number of points.
points = np.linspace(-5, 5, 256)
y1 = np.tanh(points) + 0.5
y2 = np.sin(points) - 0.2
fig,ax = plt.subplots(dpi=200)
ax.plot(points,y1)
ax.plot(points,y2)
ax.set_xticks(np.linspace(-5,5,9))
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
ax.spines['left'].set_position(('data',0))
ax.spines['left'].set_color('black')
ax.spines['bottom'].set_position(('axes',0.5)) # we could use (data,0)
ax.spines['bottom'].set_color('black')
plt.show()
points = np.linspace(-5, 5, 256)
y1 = np.tanh(points) + 0.5
y2 = np.sin(points) - 0.2
fig, axe = plt.subplots(nrows=1, ncols=2, figsize=(14, 3.5), dpi=400)
axe[0].plot(points, y1)
axe[0].plot(points, y2)
axe[1].plot(points, y1)
axe[1].plot(points, y2)
axe[1].set_xticks(np.linspace(-5, 5, 7))
axe[1].tick_params(width=0.5, colors='b')
axe[1].spines['right'].set_color('none')
axe[1].spines['top'].set_color('none')
axe[1].spines['left'].set_position(('data', 0))
axe[1].spines['bottom'].set_position(('axes', 0.5))
ax.spines['left'].set_color('black')
ax.spines['bottom'].set_color('black')
fig,(ax1,ax2) = plt.subplots(1,2,dpi=200,figsize=(10,6))
ax1.plot(points,y1)
ax1.plot(points,y2)
ax2.plot(points,y1,label="tanh")
ax2.plot(points,y2,label="sin")
ax2.legend()
plt.show()
Customizing legend properties
As with other elements in a figure, legend supports many customizable properties, including location, display style, box style, and shadow. The following are some of the most used properties:
-
loc
: The location of the legend. The most important and commonly used attribute. The strings 'upper left', 'upper right', 'lower left', 'lower right' place the legend at the corresponding corner of the axes/figure. The strings 'upper center', 'lower center', 'center left', 'center right' place the legend at the center of the corresponding edge of the axes/figure. -
fontsize
: The font size of the legend. -
ncol
: The number of columns that the legend will have. The default value is 1. -
frameon
: Controls whether the legend will be drawn with frame. -
shadow
: Controls whether a shadow will be drawn behind the legend. -
title
: Sets a title for the legend. -
facecolor
: Sets the legend’s background color. -
edgecolor
: Sets the legend’s frame color.
ax.legend(loc='upper center', title="This is a legend", shadow=True, ncol=2, facecolor='r')
fig, axe = plt.subplots(nrows=1, ncols=2, dpi=800, figsize=(12, 4))
axe[0].plot(points, y1)
axe[0].plot(points, y2)
axe[0].set_xticks(np.linspace(-5, 5, 9))
axe[0].tick_params(width=2, colors='b')
axe[0].spines['right'].set_color('none')
axe[0].spines['top'].set_color('none')
axe[0].spines['left'].set_position(('data', 0))
axe[0].spines['bottom'].set_position(('axes', 0.5))
axe[1].plot(points, y1, label="tanh")
axe[1].plot(points, y2, label="sin")
axe[1].set_xticks(np.linspace(-5, 5, 9))
axe[1].tick_params(width=2, colors='b')
axe[1].spines['right'].set_color('none')
axe[1].spines['top'].set_color('none')
axe[1].spines['left'].set_position(('data', 0))
axe[1].spines['bottom'].set_position(('axes', 0.5))
ax.spines['left'].set_color('black')
ax.spines['bottom'].set_color('black')
axe[1].legend(loc="upper left",frameon=False )
plt.show()
What is annotate?
Annotate is a piece of text that identifies a specific data point on a graph, designed to help users understand charts. For example, annotate can be used to give a detailed explanation of the inflection point of a chart.
Adding a basic annotation
-
xy
: The point (x, y) to be annotated, which is a tuple. -
xytext
: The position (x,y) where the text will appear. None defaults to xy. -
xycoords
: The coordinate system that xy is given in.(xycoords=‘data’ ) -
textcoords
: The coordinate system that xytext is given in. -
arrowprops
: The properties used to draw an arrow between xy and xytext.
fig,ax = plt.subplots(dpi=200)
ax.plot(points,y1)
ax.plot(points,y2)
ax.annotate("1.464=tanh(2)+0.5",xy=(2,1.468),xycoords="data",xytext=(0.4,-40),textcoords='offset points',arrowprops=dict(arrowstyle="->",color="black", connectionstyle="arc3,rad=.5"))
fig, axe = plt.subplots(dpi=800, figsize=(9, 5))
axe.plot(points, y1)
axe.plot(points, y2)
axe.legend(["tanh", "sin"])
axe.annotate("style1", xy=(2, 1.464), xycoords="data",
xytext=(0.4, -40), textcoords='offset points',
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.5",color="black"),
bbox=dict(boxstyle="round", fc="none", ec="gray"))
axe.annotate("style2", xy=(2, 1.464), xycoords="data",
xytext=(-200, -40), textcoords='offset points',
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.5",color="black"),
bbox=dict(boxstyle="round", alpha=0.1),)
axe.annotate("style3", xy=(2, 1.464), xycoords="data",
xytext=(-160, -80), textcoords='offset points',
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.5",color="black"),
bbox=dict(boxstyle="round4,pad=.5", fc="0.3"))
What is text?
Text is basically a simpler version of annotate. Unlike annotate, we don’t need to anchor our text to one specific data location.
text(0.5, 0.5, 'function', horizontalalignment='center',verticalalignment='center', transform=ax.transAxes)
If we want to put a frame around the text, we can use the option bbox. The example code below adds a box with a red background to our text.
text(10, 20, "function", bbox=dict(facecolor='red', alpha=0.5))
fig, axe = plt.subplots(figsize=(7, 3.5), dpi=300)
axe.plot(points, y1)
axe.plot(points, y2)
axe.legend(["tanh", "sin"])
axe.text(-2.5, 0.5, "two function\nOne\nTwo", bbox=dict(facecolor='red', alpha=0.5))
plt.show()
fig, axe = plt.subplots(figsize=(7, 3.5), dpi=800)
axe.plot(points, y1)
axe.plot(points, y2)
axe.legend(["tanh", "sin"])
eq = r"$\int_a^b{\sin(x)} dx$"
font = {'family': 'serif',
'color': 'darkred',
'weight': 'normal',
'size': 16,
}
axe.text(-3, 0.18, eq, font)
fig, axe = plt.subplots(figsize=(7, 3.5), dpi=300)
axe.plot(points, y1)
axe.plot(points, y2)
axe.legend(["tanh", "sin"])
axe.annotate("1.464=tanh(2)+0.5", xy=(2, 1.464), xycoords="data",
xytext=(0.4, -40), textcoords='offset points',
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.5"))
axe.minorticks_on()
axe.grid(which='major', linestyle='-', linewidth='0.5', color='blue')
axe.grid(which='minor', linestyle=':', linewidth='0.5', color='red')
fig, axe = plt.subplots(figsize=(7, 3.5), dpi=300)
axe.plot(points, y1)
axe.plot(points, y2)
axe.legend(["tanh", "sin"])
axe.set_title("two functions")
axe.set_title("two functions left", loc="left")
axe.set_title("two functions right", loc="right")
fig, axe = plt.subplots(1,2, figsize=(14, 3.5), dpi=300)
axe[0].plot(points, y1)
axe[0].set_title("tanh functions")
axe[1].plot(points, y2)
axe[1].set_title("sin functions")
fig.suptitle("tanh & sin function")
fig, axe = plt.subplots(nrows=2, ncols=2, dpi=800)
plt.tight_layout()
axe[1][0].set_title("the third subplot")
axe[1][1].set_title("the forth subplot")
x = np.linspace(-4, 4, 200)
fig, axe = plt.subplots(dpi=300)
# RGB
axe.plot(x, x + 2, color=(0.1, 0.6, 1.0), label="RGB")
# HEX RGB
axe.plot(x, x + 3, color="#6F4F3F", label="Hex")
# single color letter
axe.plot(x, x + 4, color='r', label="single letter")
# color name
axe.plot(x, x + 5, color='green', label="color name")
# Tableau color
axe.plot(x, x + 6, color='tab:olive', label="Tableau")
# gray level
axe.plot(x, x + 7, color='0.7', label="gray level")