There are several ways to generate arrays we use in matplotlib. Often we need to create an evenly spaced x axis for our graph. Here are two numpy methods to create a one dimensional array
# Ex2.2.0
import numpy as np
x=np.arange(5)
print(x,'\n\n')
x=np.arange(1,10,.5)
print(x,'\n\n')
x=np.linspace(0, 10, 5)
print(x,'\n\n')
We can generate an array of random numbers using the following:
# Ex2.2.0
# generating a one dimensional array
import numpy as np
x=np.random.randint(1, 50, 20)
print(x,'\n\n')
# generating a two dimensional array: here we generate 2 rows and 5 columns
x=np.random.randint(1, 50, (2,5))
print(x,'\n\n')
x=np.logspace(0,2,50)
print(x)
The first example is a simple plot plot in which we plot a cubic polynomial $y=x^3$ versus $0 \le x \le 2$ . We can add additional arguments to plt.plot(c=‘color_string’,linestyle=‘style_string' )
The basic colors are:'b' as blue 'g' as green 'r' as red 'c' as cyan 'm' as magenta 'y' as yellow'k' as black'w' as white.
Simple line styles can be defined using the strings "solid", "dotted", "dashed" or "dashdot".
Experiment: In Ex2.2.1 try the following:
# Ex2.2.1
import matplotlib.pyplot as plt
import numpy as np
# Creates Numpy array for x values
x = np.linspace(0, 2, 100)
# Computes y(x) for each graph
plt.plot(x, x**3, label='cubic')
# creates labels of the two axes
plt.xlabel('x')
plt.ylabel('y')
# creates a title
plt.title("plotting $y=x^3$ ")
# displays the final plot
plt.show()
Experiment: In Ex2.2. try the following:
Change this example to plot two line-plots, one for sin(x) and the second for sin(x)cos(x). let x range from 0 to 2np.pi. Change the labels for the graphs. NOTE: The legend box is automatically relocated to the ‘best’ position so as not to interfere with the lines drawn.
# Ex2.2.2
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2, 100)
# Computes y(x) for each graph
plt.plot(x, x, label='linear')
plt.plot(x, x**2, label='quadratic')
plt.plot(x, x**3, label='cubic')
# creates labels of the two axes
plt.xlabel('x label')
plt.ylabel('y label')
# creates a title
plt.title("Comparing Linear, Quadradic, and Cubic Plots")
# creates the legend box in upper left to identify each of the graphs
plt.legend()
# displays the final plot
plt.show()
In these two examples we will introduce plt.figure(figsize=(5,5)). (line4). The argument figsize is given by a tuple (W,H) where the width W and the height H are specified in inches. HOWEVER, the actual display depends on the device on which the images will be displayed. This difference occurs because Jupyter notebook is set for 782 dpi, while your monitor is likely different. If you wish, you can determine the scaling factor. On my monitor the scaling is 0.5. So, if I want a plot if 5 in by 5 in, I need to specify 10 by 10.
Other differences in this example is that we are specifying the x and y coordinates as a function of a parameter t. Plotting a sine wave and a cosine wave on x and y axes will produce a circle—one of a class of Lissajous diagrams. Remember, you must use np.sin( ) and np.cos( ) and np.pi in order to specify the functions.
In Ex 2.2.4 we display the Lissajous Diagram for two sine waves of differing frequencies. The ratio of the number of lobes in the Lissajous diagram in the x:y direction is the ratio of the frequencies. 2:3 on the horizontal (x):vertical(y)
# Ex2.2.3
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(5,5))
t=np.linspace(0,np.pi,200)
x=10*(np.sin(2*t))
y=10*(np.cos(2*t))
plt.plot(x, y)
plt.show()
# Ex2.2.4
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(5,5))
t=np.linspace(0,6*np.pi/3,200)
x=10*(np.sin(3*t))
y=10*(np.sin(2*t))
plt.plot(x, y)
plt.show()
The following example and explanation is adapted from a matplotblog by Tejas Sanap. Consider the following problem from physics. Suppose we want to plot the velocity and the displacement of an object as it falls in earth’s gravitational field (). The equations of motion become: $$v=gt$$ $$d=.5gt^2$$ Notice that using a common y axis scale, we compress the velocity plot. It would be nice to be able to include a y-axis for displacement and one for velocity.
# Ex2.2.5
import matplotlib.pyplot as plt
import numpy as np
g=9.8
t=np.linspace(0,10,100)
v=g*t
d=.5*g*t**2
plt.figure(figsize=(9,7))
plt.plot(t,d,c='b')
plt.plot(t,v,c='r')
plt.xlabel('time')
plt.ylabel('distance and velocity')
plt.grid(True)
plt.show()
matplotlib is based on an object hierarchy. The BIGGEST PROBLEM in getting started with matplotlib is to confuse Axis with Axes. In this context, Axes is not the plural of Axis. The relationship among matplotlib objects is shown in the preceeding diagram. Let’s start with what is called an Axes. The Axes is comprised of a line2D, Text, XAxis, and YAxis. In fact, there may be more than one Axes as a child of Figure. Likewise, each of the sub objects of Axes may have multiple instances. Think of the last example in which both the velocity and distance are plotted. Each Axis (X and Y) have labels. Each label has ticks.
Returning to the physics problem described earlier, we realize that in order to have a better looking rendition of the data, we should plot distance and velocity on two separate Axes, each with a different Axis, and scale. We can use one Figure containing two Axes. How do we accomplish this?.
# Ex2.2.6
import matplotlib.pyplot as plt
import numpy as np
g=9.8
t=np.linspace(0,10,100)
v=g*t
d=.5*g*t**2
# Creates an axes ax1 in a figure named fig
fig, ax = plt.subplots(1,2)
ax1=ax[0]
ax2=ax[1]
# Creates the labels for each Axis associated with ax1
ax1.set_ylabel("distance (m)")
ax1.set_xlabel("time")
# Creates the labels for each Axis associated with ax2
ax2.set_ylabel("velocity (m/s)")
ax2.set_xlabel("time")
# Plots the data for d in ax1 and the data for v in ax2
ax1.plot(t, d, c='b')
ax2.plot(t, v, c='g')
# Set display parameters
fig.set_size_inches(10,5)
plt.show()
Although we will eventually create 2 axes objects, we begin with creating a single object ax1 (line 9). Notice that the arguments of the subplots() function is null. That means that we get the default of a single axes object, which we name ax1. After we set the labels for each axis object, we use the method .plot applied to the ax1 object to associate the distance data with the curve in ax1.
At this point we do something different. In line 16 we create a clone of ax1 which we define to be ax2. When we set the ylalbel for ax2 (line 18), we create a twin in which the two axes share the same x_axis, but each has a different y_axis.
After we add data to ax2, set the figure size, we than display the plot.
# Ex2.2.7
import matplotlib.pyplot as plt
import numpy as np
g=9.8
t=np.linspace(0,10,100)
v=g*t
d=.5*g*t**2
# Creates an axes ax1 in a figure named fig
fig, ax1 = plt.subplots()
# Creates the labels for each Axis associated with ax1
ax1.set_ylabel("distance (m)")
ax1.set_xlabel("time")
# Plots the data for distance
ax1.plot(t, d, c='b')
# Creates an axes ax2 which is a twin of ax1
ax2 = ax1.twinx()
# Creates the labels for each Axis associated with ax2
ax2.set_ylabel("velocity (m/s)")
ax2.plot(t, v, c='g')
# Set display parameters
fig.set_size_inches(7,5)
plt.show()
The data table displays sales of ice cream as a function of the temperature. In this example we create a scatter plot of this empirical data. This example is taken from https://www.mathsisfun.com/data/scatter-xy-plots.html In this example the emperical data is entered into two lists T and S. After setting the labels, we specify that we want to plot a scatter plot by using plt.scatter(T,S). In this example, we are HIDING THE DETAIL OF THE FIGURE OBJECTS. They are being generated by default behind the sceens. We could, however, have greater control over the plots by defining the axes, etc. In this case, our plot is simple, and we need not do this.
Compare lines 5 in this example: plt.xlabel('Temperature degrees C')
to line 12 in the preceeding example: ax1.set_xlabel("time")
In Ex 2.2.8 we have defined ax1 and are explicitly adding the xlabel as a object to the x-axis object. In Ex 2.2.9 this is hidden. The programmer needs to decide which is more important simplicity over greater control of the graphic display.
# Ex 2.2.9
import matplotlib.pyplot as plt
T=[14.2,16.4,11.9,15.2,18.5,22.1,19.4,25.1,23.4,18.1,22.6,17.2]
S=[215,325,185,332,406,522,412,614,544,421,445,408]
plt.xlabel('Temperature degrees C')
plt.ylabel('Ice Cream Sales in $')
plt.scatter(T,S)
plt.show()
In the last example we plotted empirical data which was stored in two lists. In this example we want to plot a histogram of a finite sample drawn from a normally distributed random variable. For that we can use the following Numpy function: np.random.normal ( ). There are three key arguments: the mean, standard deviation and the sample size. In Ex 2.2.10 we set the mean and the standard deviation in lines 5 & 6. We want to plot a series of histograms for different sample sizes: 500,1000,1500, and 2000. Thus, we generate the sampled histogram data and the histogram plotting function embedded in a for loop with nsize in range(500.2001,500). Why 2001? Recall that the end value of the range function is exclusive while start number is inclusive. Thus, the last value of nsize that will be executed in the loop is 2000.
We are using the plt.hist() fuction which has a first argument as the data passed to the function—this was generated in line 8. While we have not talked about arguments in functions like plt.hist( ), if you were to look at the documentation of this function (or any method embedded in python and its packages, you will find a rather daunting list of arguments. The definition of these functions uses the keyword argument **kwargs. From the point of view of the user, any argument that the user wants to specify is included at the end of the argument list; in this case bins=50, color=‘b’ . The function replaces the default value of the bins and color variable with the value specified. The keyword bins stands for the number of bars that will appear in the histogram plot. Data is collected into these bins, before plotting. The larger the number of bins, the smoother the plot. Incidentally, using color =‘b’ is the same as c=‘b’ an also color=‘blue’. More on color later.
Experiments with Ex 2.2.10
# Ex 2.2.10
import numpy as np
import matplotlib.pyplot as plt
# Generate normally distributed random data
mu=170
sig=10
for nsize in range(500,2001,500):
data = np.random.normal(mu, sig, nsize)
plt.hist(data, bins=50, color='b')
s1='sample size='+str(nsize)
plt.title(s1)
plt.show()
In constructing 3-D plots we not only need to import numpy and pyplot, but we must import mplot3d from mpl_toolkits. even though there is no specific reference to this within the program we write, it is used by pyplot (plt) when we define an axes (ax) in line 12. that call to plt.axes has an argument projection=‘3d’ mpl_toolkits.mplot3d provides some basic 3D plotting (scatter, surf, line, mesh) tools. Not the fastest or most feature complete 3D library out there, but it ships with Matplotlib and thus may be a lighter weight solution for some use cases. Check out the mplot3d tutorial for more information.
In the next example we will graph a 3-D plot of a function spiraling in the xyz plane. Specifically that function is defined in lines 14 thru 16. First, z is defined as an array containing 100 points, from 0 to 100. Since z is an array, x and y will also be arrays.
z = np.linspace(0, 1, 100) x = z np.sin(25 z) y = z np.cos(25 z)
If z were to be a constant value, and we were to graph this function in the the x-y plane we would get a circle—a one lobe by one lobe Lissajous diagram (see Ex 2.2.3 . However, if we define an array of values for z using the linspace function from Numpy (line 13) the larger the value of z, the larger the radius of the circle. Now if we plot this in 3-space x,y,z we get a spiral.
In lines 19-21 we establish the labels for the each axis x,y, and z.
Finally, we plot the 3-D line plot. The first three arguments are the x,y, and z arrays defined in 14-16. Optionally, we set the color of the line to green.
Experiment with Ex 2.11
# Ex2.2.11
# importing mplot3d toolkits and numpy
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
# Setting the size of the figure
plt.figure(figsize=(10,10))
# setting the axes for 3-D projection and defining the axes
ax = plt.axes(projection ='3d')
# generating the data
z = np.linspace(0, 1, 100)
x = z * np.sin(25 * z)
y = z * np.cos(25 * z)
# establishing the axis labels
ax.set_xlabel('X', fontsize=20)
ax.set_ylabel('Y', fontsize=20)
ax.set_zlabel('Z', fontsize=20)
# plotting
ax.plot3D(x, y, z, c='green')
ax.set_title('A spiral path in 3D')
plt.show()
In order to plot surfaces we will need to define a mesh of (x,y) values above which we will plot z, the height of the surface. While meshpoint( ) does not generate a matrix of tuples which are the coordinates in the x-y plane, the output of the function creates a 2-D array to represent the values of x and a second 2-D array to represent the values of y. First let’s look at the way we will use the function.
x,y= np.meshgrid(x_value, y_value)
x_value and y_value are lists of values above which we want to plot the surface. In the example program below, both x_value and y_value are 3x1 arrays. The outputs of meshgrid( ) are two 3x3 arrays. Each row in the first array (see red array in figure) repeats the values in the array x_value, while each column (blue array) repeats the values in y_value as columns in the blue array. To the right of these two outputs of meshgrid is an explanation of how these two arrays are used to generate the meshpoints. NOTE: these are not INDICES, but VALUES of x & y respectively, at each mesh point. Line 12 defines z as the sum of x+y. Since x and y are both 3x3 arrays you would expect z to be a 3x3 array. The sum of x and y is done point by point thru the array. You can confirm the result from the statement print(z) line 14.
# demo describing np.meshpoint( )
import numpy as np
# define meshpoint in the x,y plane
x_value=(1, 2, 3)
y_value=(5, 6, 7)
x,y = np.meshgrid(x_value, y_value)
print('the shape of x =',np.shape(x))
print(x,'\n')
print('the shape of y =',np.shape(y))
print(y,'\n')
# define the surface to be plotted
z = x+y
print('the shape of z =',np.shape(z))
print(z)
We begin by importing the appropriate packages. There is a new one here called cm from matplotlib. We will come back to describe why and how we use this package later.
Lines 6-9 are the same as we used in 2.2.12.1 . In this example, we will plot a more complex surface defined by:
In this problem since both x_value and y_value are 1x100 arrays, x,y, and z will each be 100x100 arrays.
Line 15 creates a figure named fig and establishes its size. Line 16 defines the axes (remember the difference between axes and axis) as a projection of a 3-d object. The surface plot is defined in line 19. It is given a name surf, and the three 100x100 arrays x,y, and z are arguments. The argument (which is an optional **kwargs is
cmap=cm.coolwarm The package we imported called cm from matplotlib contains a variety of color maps. Here are a few from that package.
Here are a few of a very large number of colormaps you can use in surface plots. Line 23 of the code places a colorbar mapping z values to the gradient of color. Critical to using this is to name the surface (line 19 defines the surface as surf)
Line 21 sets the title. We have added something new here. Notice the string enclosed between two dollar signs: $\cos(x^2+y^2)$. This indicates that this is LaTeX code. LaTeX is a typesetting language that we use to represent mathematical equations. It is built into many word processors. Using the backslash with cos \cos( ) is interpreted as the cosine function. The ^ represents raised to a power x^2 is $x^2$. For more information on LaTeX you can see http://drfresearch.com/index-other.html .
Line 24 of the code places a colorbar mapping z values to the gradient of color. Critical to using this is to name the surface (line 19 defines the surface as surf)
It is important to realize that the size of the grid you choose will impact the smoothness of the surface plot. Try changing lines 7 and 8 to have 100 points and finally 50 points.
Using the chart above, try different colormap names.
# Ex 2.2.12.2
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
# define meshpoint in the x,y plane
x_value=np.linspace(-2, 2, 1000)
y_value=np.linspace(-2, 2, 1000)
x,y = np.meshgrid(x_value, y_value)
# define the surface to be plotted
z = np.cos(x**2 + y**2)
# set up the figure and the axes
fig = plt.figure(figsize=(15,10))
ax = plt.axes(projection='3d')
# plot the surface
surf=ax.plot_surface(x, y, z,cmap=cm.coolwarm, edgecolor='none')
ax.set_title('Surface plot of $\cos(x^2+y^2)$ \n\n',fontsize=25)
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
# Ex 2.2.13
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
# define meshpoint in the x,y plane
x_value=np.linspace(-2, 2, 1000)
y_value=np.linspace(-2, 2, 1000)
x,y = np.meshgrid(x_value, y_value)
# define the surface to be plotted
z = np.cos(x**2 + y**2)
# set up the figure and axes
fig = plt.figure(figsize=(10,10))
ax = plt.axes()
# specify plotting for a contour map
cp=ax.contour(x,y,z, cmap=cm.coolwarm, levels=[-1,-.75,-.5,-.25,0,.25,.5,.75,1])
ax.clabel(cp, fontsize=9, inline=True)
ax.set_title('Contour plot of $\cos(x^2+y^2)$ \n\n',fontsize=25)
plt.show()
In order to display contour plots, we need to import matplotliblpyplot and numpy (lines 2-3). Second, we need to create an array of values for the x and y axes. Each of these will be a 1D array. The third step is to create a 2-D grid for the x-y axis (line 10).Line 12 sets up the axes for the grid. The agrument (1,1) of plt.subplots establishes that there is one row and one column in the grid. Line 15 creates the Z dimension form the [X,Y] grid values.
© Donald R. Falkenburg
Last updated 4/29/23