Matplot lib - All your plotting functions under one roof (almost!)

Matplotlib is a simple (most of the time) plotting library.

So let's have a try!


In [ ]:
# This will plot a simple scatter graph of points. 
# The points will have all different sizes just for visual appearance, as well as varied colours
%matplotlib inline
# Import the required libraries
import numpy as np
import matplotlib.pyplot as plt

In [ ]:
# Lets say we want to plot 50 points
N = 50

In [ ]:
# Generate some random data
x = np.random.rand(N)
y = np.random.rand(N)

In [ ]:
# Add a random colour field
colors = np.random.rand(N)

In [ ]:
# Alter the size of the particles randomly
area = np.pi * (15 * np.random.rand(N))**2  # 0 to 15 point radiuses

In [ ]:
# Here we create a figure in an object orientated fashion, and call is 'ax' 
fig = plt.figure()
ax = fig.add_subplot(111)

# Let's plot it! Simple right? Plot x, y. Alpha = the transparency of the points - very useful! 
ax.scatter(x, y, s=area, c=colors, alpha=0.5)

# Now for some labels....and a title (they always help)
ax.set_xlabel('Random x')
ax.set_ylabel('Random y')
ax.set_title('Awesome! (but kind of pointless...)')

Exercise 1

Now lets have a look at some real data!


In [ ]:
# First of all, lets read some data from a CSV file. 
#"Figure 1. Average Global Sea Surface Temperature, 1880-2015",,,
#Source: EPA's Climate Change Indicators in the United States: www.epa.gov/climate-indicators,,,"Data source: NOAA, 2016",,,
# Units: temperature anomaly (°F),,,
# https://www.epa.gov/sites/production/files/2016-08/sea-surface-temp_fig-1.csv 

# Import our libraries
import csv
import matplotlib.pyplot as plt
import os

In [ ]:
# We first need to find our file. 
file_name = os.path.join(os.path.pardir, 'data', 'sea-surface-temp_fig-1.csv')

2. numpy.genfromtxt()


In [ ]:
## Header is 6 lines and we are going to read in the data
skip_rows = 6

In [ ]:
## Read 'file_name' and call it 'data' 
## This is a simple .csv file. Go into the folder 'Data' and open it in Excel if you don't believe us! 
## Set delimiter for csv, we will skip the headers, and names=True means that columns have names we will use. 
data = np.genfromtxt(file_name, delimiter=',', skip_header=skip_rows, names=True, dtype=None)

In [ ]:
## Name the data based on the column names
years = data['Year']
temperature = data['Annual_anomaly']

Note: pandas.read_csv() function has a similar functionality and returns similar data structure.

3. Plot a line graph of Average Ocean Temperature from 1880-Present


In [ ]:
### Time to create our plot
### fig sets up a blank figure for us.
fig = plt.figure()

In [ ]:
### We are now going to use object orientated apporoach and call it 'ax'
ax = fig.add_subplot(111)

In [ ]:
### Plot X, Y using 'ax' our blank figure. Colour (c) = 'red'...try changing this! 
#ax.plot(x, y, c='red')

Formatting:


In [ ]:
### How about adding some labels? 
#ax.set_xlabel('Year')
#ax.set_ylabel('Temperature (oF)')
#ax.set_title('Annual Anomaly')

Try looking at the data from the 1960's to the present day. You can do this by just changing the 'x' and 'y' axis


In [ ]:
## This one sets the limits of the x and y axis. 
#ax.set_xlim(..., ...)
#ax.set_ylim(..., ...)

4. Save the figure


In [ ]:
# fig.savefig('awesome_figure.png', dpi=300, bbox_to_inches='tight')

Now lets see if we can make some subplots


In [ ]:
# Here we are going to loop over the same dataset twice and product a subplot with a different colour. 
# Two data arrays are created - uncomment 'data' to see what the output looks like. 
data = [temperature for i in range(2)]

In [ ]:
# Create a colour scheme up to the value of 12. A simple array of numbers. 
colours = np.linspace(0.2,6,12) 

### Trying playing with the value '6' what does it do and how does it effect the output? 
### Why not try the other values too....remember to save your origional code! Use comments '#' to save it for later.

In [ ]:
# Set a figure of 2 Vertical, by 1 Horizonal 
fig, ax = plt.subplots(2, 1)

# Loop over the two data arrays, 
for ix, arr, col in zip(ax.flat, data, colours):
    ix.plot(arr, color=str(col))

Now you can see the x axis has gone wrong!

I'm not going to give you a solution, but maybe you can scrape the internet and find one!

Stackoverflow is full of solutions. Remember that!

Exercise 2

The next section is based upon marine data taken from the ICES dataset on the European Continental Shelf


In [ ]:
file_name = os.path.join(os.path.pardir, 'data', 'Shelf_sea_nuts.csv')
### Header is 1 line and we are going to read in the data
skip_rows = 1

In [ ]:
### Read 'file_name' and call it 'data' 
### This is a simple .csv file. Go into the folder 'Data' and open it in Excel if you don't believe us! 
data = np.genfromtxt(file_name, delimiter=',', names=True, dtype=None)
print(data.dtype)
print("What is that? We have the headers printed out for us!")
print("Maybe we should do something with these.... can you guess where they go?")

In [ ]:
### Name the data based on the column names
#ICES_year = data['']
#ICES_temperature = data['']
#ICES_Oxygen = data['']
#ICES_Nitrate = data['']

Task:

Try to produce three plots of the above data.

If you are feeling very adventureous, how about functionalising it!

The simple task is to produce a scatter plot for each variable above, changing the colour, and transparency of the points.

If you have time, how about using numpy.mean to mean the data via year, and then plot a line graph. If you get this far, try changing the 'linestyle' or 'ls' as you have done with colour and transparency.


In [ ]:
#fig = plt.figure()
#ax = fig.add_subplot(111)

#ax.???(???, ???, color=???, alpha=???)  # hint how about we try a scatter plot? 
#ax.set_xlabel('???')
#ax.set_ylabel('???')
#ax.set_title('???')

Example of what else you can do:

Scatter Plot and colour the points by frequency


In [ ]:
### Create some random numbers
n = 100000
x = np.random.randn(n)
y = (1.5 * x) + np.random.randn(n)

In [ ]:
### Plot the data without colouring the points by frequency
fig1 = plt.figure()
ax = fig1.add_subplot(111)

    ### Formatting
ax.plot(x,y,'.r')
ax.set_xlabel('Random X')
ax.set_ylabel('Random Y')

In [ ]:
### Estimate the 2D histogram we are using a numpy function and binning the data. 
    ### What happends if you play around with the value 200???
#nbins = 200
H, xedges, yedges = np.histogram2d(x,y,bins=nbins)

# H needs to be rotated and flipped
H = np.rot90(H)
H = np.flipud(H)

In [ ]:
# Mask zeros
Hmasked = np.ma.masked_where(H==0,H) # Mask pixels with a value of zero

In [ ]:
# Plot 2D histogram using pcolor
fig2 = plt.figure()
ax = fig2.add_subplot(111)

ax.pcolormesh(xedges,yedges,Hmasked)
ax.set_xlabel('Random X distribution')
ax.set_ylabel('Random Y distribution')

Example - Contour plots


In [ ]:
#### Create a function for generating visual data
def f(x,y):
    return (1-x/2+x**5+y**3)*np.exp(-x**2-y**2)

In [ ]:
### Creates data
n = 256
x = np.linspace(-3,3,n)
y = np.linspace(-3,3,n)
X,Y = np.meshgrid(x,y)

In [ ]:
### Object orientated 
fig4 = plt.figure()
ax = fig4.add_subplot(111)

### Plot a contour plot
ax.contourf(X, Y, f(X,Y), 8, alpha=.75, cmap=plt.cm.hot)
C = ax.contour(X, Y, f(X,Y), 8, colors='black', linewidth=.5)

### Do you want values inline with the contours? If so, uncomment me below!
#ax.clabel(C, inline=1, fontsize=30)
print("Did you label the values inline?")

Example 1 - Quiver Plots


In [ ]:
### Creates data and puts it onto a grid
n = 8
X,Y = np.mgrid[0:n,0:n]

In [ ]:
### Plot quiver
fig5 = plt.figure()
ax = fig5.add_subplot(111)

ax.quiver(X,Y)

Example 2 - Quiver Plots


In [ ]:
### Creates random data 'X' 'Y' 'U' 'V'
n = 8
X,Y = np.mgrid[0:n,0:n]
T = np.arctan2(Y-n/2.0, X-n/2.0)
U,V = R*np.cos(T), R*np.sin(T)

In [ ]:
### Creates some data that we will use for the colouring of the arrows.
R = 10+np.sqrt((Y-n/2.0)**2+(X-n/2.0)**2)

In [ ]:
# Plots using object orientated way
fig6 = plt.figure()
ax = fig6.add_subplot(111)

# Make a quiver plot. and colour is using 'R'
ax.quiver(X,Y,U,V,R, alpha=.5)

### If you'd like to make it look a little more perfected and better contrast, try this one: 
#ax.quiver(X,Y,U,V, facecolor='None', linewidth=.5)
 
# Set the limits.
ax.set_xlim(-1,n)
ax.set_ylim(-1,n)