Difference between revisions of "Python:Plotting"

From PrattWiki
Jump to navigation Jump to search
Line 1: Line 1:
 
This page will primarily go over some examples of different ways to plot data sets. It assumes
 
This page will primarily go over some examples of different ways to plot data sets. It assumes
import matplotlib.pyplot as plt
+
<source lang="python">
 +
import math as m
 +
import numpy as np
 +
import matplotlib.pyplot as plt
 +
</source>
 
is in the program.
 
is in the program.
  
Line 244: Line 248:
 
</source>
 
</source>
 
-->
 
-->
 +
 
=== The <code>plt.savefig()</code> Function ===
 
=== The <code>plt.savefig()</code> Function ===
 
The <code>plt.savefig()</code> function is used to save a plot to a file.  The type of sile is determined by the extension of the file name.  For example,  
 
The <code>plt.savefig()</code> function is used to save a plot to a file.  The type of sile is determined by the extension of the file name.  For example,  
Line 250: Line 255:
 
  plt.savefig('blah.pdf')
 
  plt.savefig('blah.pdf')
 
will save it to a PDF.  From the help file for the command, Most backends support png, pdf, ps, eps and svg.
 
will save it to a PDF.  From the help file for the command, Most backends support png, pdf, ps, eps and svg.
<!--
+
 
 
=== Example ===
 
=== Example ===
[[File:Usfplot.png|thumb|Example showing a figure split into 2x3 subplots with subplot 3 holding an empty axis and subplot 4 holding a graph of the unit step function.]]
+
[[File:UsfplotPython.png|thumb|Example showing a figure split into 2x3 subplots with subplot 3 holding an empty axis and subplot 4 holding a graph of the unit step function.]]
The following MATLAB code demonstrates how to fill the fourth window
+
The following Python code demonstrates how to fill the fourth window
of a 2x3 plot figure, save the figure as a PostScript file, and
+
of a 2x3 plot figure and save the figure as a PNG file; the resulting figure is in the thumbnail at right.
preview it with <code>kghostview</code>; the resulting figure is in the thumbnail at right.
+
<source lang="python">
<source lang="matlab">
+
# Import required modules
% Create a vector of numbers between -1 and 1 with 0.001 between numbers
+
import numpy as np
x=-1:0.001:1;
+
import matplotlib.pyplot as plt
 
 
%This formula for usf is one of several ways to define the unit step function
 
usf = @(t) t>=0;
 
  
%Create a figure with two rows of three figures and make subplot 4 (bottom row left) current
+
# Create a 100 numbers between -1 and 1
subplot(2,3,4)  
+
x = np.linspace(-1, 1, 100);
  
% Plot the values of the function usf(x) against the vector x
+
# This formula for usf is one of several ways to define the unit step function
plot(x, usf(x))  
+
def usf(t):
 +
    return (t>=0)*1.0;
  
% Change the axes so the function is not covered by the subplot box
+
# Create a figure with two rows of three figures and make subplot 4 (bottom row left) current
axis([-1, 1, -1, 2])
+
plt.figure(1)
 +
plt.clf()
 +
plt.subplot(2, 3, 4)
  
% Give the current subplot a title
+
# Plot the values of the function usf(x) against the vector x
title('Unit Step Function')
+
plt.plot(x, usf(x))  
  
% Set the x-label
+
# Change the axes so the function is not covered by the subplot box
xlabel('x')
+
plt.axis([-1, 1, -1, 2])
  
% Set the y-label
+
# Give the current subplot a title
ylabel('u(x)')
+
plt.title('Unit Step Function')
  
% Make subplot 3 (top row right) current - it will be empty in the example
+
# Set the x-label
subplot(2,3,3)  
+
plt.xlabel('x')
  
% Use landscape (wide) orientation
+
# Set the y-label
orient landscape
+
plt.ylabel('u(x)')
  
% Send the current figure to a file named usfplot.eps;
+
# Make subplot 3 (top row right) current - it will be empty in the example
% Note that the `.eps' is automatically added
+
plt.subplot(2,3,3)
print -deps usfplot
 
  
% The "!" character lets MATLAB act as if you were at a regular terminal.
+
# Send the current figure to a file named usfplot.png
% This command thus lets you view usfplot.eps using UNIX's kghostview
+
plt.savefig('usfplot.png')
!kghostview usfplot.eps
 
 
</source>
 
</source>
<!--
 
\begin{figure}[h!]
 
\begin{center}
 
\epsfig{file=../GENERAL/MATLAB/sixplot.ps, width=2.4in, angle=90}
 
\caption{Sample Output}
 
\end{center}
 
\end{figure}
 
 
  
% LocalWords:  MATLAB's filename kghostview
 
-->
 
<!--
 
 
== General Plotting Tips ==
 
== General Plotting Tips ==
 
You must make sure that your data sets are presented properly.  Here are some guidelines:
 
You must make sure that your data sets are presented properly.  Here are some guidelines:
Line 313: Line 305:
 
<tr>
 
<tr>
 
<td width=100%>
 
<td width=100%>
<source lang="matlab">
+
<source lang="python">
xlabel('{\it v}, m/s')
+
plt.xlabel('$v$, m/s')
xlabel('{\it v} (m/s)')
+
plt.xlabel('$v$ (m/s)')
xlabel('Velocity, m/s')
+
plt.xlabel('Velocity, m/s')
xlabel('Velocity (m/s)')
+
plt.xlabel('Velocity (m/s)')
xlabel('Velocity ({\it v}), m/s');
+
plt.xlabel('Velocity ($v$), m/s');
xlabel('Velocity ({\it v}, m/s)');
+
plt.xlabel('Velocity ($v$, m/s)');
 
</source>
 
</source>
 
</td></tr></table>
 
</td></tr></table>
 
:You should be consistent within a single graph as far as which version you use, and you should pick which format you believe conveys the information most efficiently and effectively.
 
:You should be consistent within a single graph as far as which version you use, and you should pick which format you believe conveys the information most efficiently and effectively.
* Make sure your titles make sense and that you have your NET ID in one of the titles for each figure you create.  If you have multiple subplots, you only need one of the titles to have your NET ID.  Typically, the title will read "DEP. VAR vs. INDEP. VAR for DESCRIPTION (NET ID)" where DEP. VAR is your dependent variable (typically on the ''y'' axis), INDEP. VAR is your independent variable (typically on the ''x'' axis), DESCRIPTION is something that will differentiation this particular plot from others that might have the same variables (for example a data, or an experiment number), and NET ID is your NET ID.
+
* Make sure your titles make sense and that you have your NetID in one of the titles for each figure you create.  If you have multiple subplots, you only need one of the titles to have your NetID.  Typically, the title will read "DEP. VAR vs. INDEP. VAR for DESCRIPTION (NetID)" where DEP. VAR is your dependent variable (typically on the ''y'' axis), INDEP. VAR is your independent variable (typically on the ''x'' axis), DESCRIPTION is something that will differentiation this particular plot from others that might have the same variables (for example a data, or an experiment number), and NetID is your NetID.
 
* Data points should be represented by symbols and model equations should be represented by lines.  Be sure to use a legend to identify each item plotted if there are multiple data sets on the same graph.
 
* Data points should be represented by symbols and model equations should be represented by lines.  Be sure to use a legend to identify each item plotted if there are multiple data sets on the same graph.
* Typically, you will want to set the axis limits such that no data point is on the figure boundary.  Certainly you do not want a line to be plotted on top of a figure boundary.  After you make a plot, if there is a data point on an edge, look at the current axes and go out a little bit. Just make sure if you end up fundamentally changing your code that you adjust the axes accordingly.  Alternately, you can use the [[#Keeping Data Off The Edge| gzoom]] function below to automatically expand the graph.
+
* Typically, you will want to set the axis limits such that no data point is on the figure boundary.  Certainly you do not want a line to be plotted on top of a figure boundary.  After you make a plot, if there is a data point on an edge, look at the current axes and go out a little bit. Just make sure if you end up fundamentally changing your code that you adjust the axes accordingly.   
* If you end up using the <code>hold on</code> command, you should only use it '''after''' the first plotting command is issued; if not, there are some parts of a typical plot that will not show up, such as the complete plot frame.   
 
  
== Keeping Data Off The Edge ==
 
Typically, you will not want data points to land on the edge of a graph.  If you are just plotting lines, this is not a problem but if you are actually putting symbols at each point, those symbols should not cross the border out of the axes.  To combat this, you can put a short program called <code>gzoom.m</code> into your directory and run it.  The default case is to add 10% to each direction of the graph in the active figure.  The first argument specifies what the expansion value should be (if you want it different from 0.1) while the second argument specifies which figure should be expanded (if you want it to be different from the active figure).  The gzoom function is:
 
<source lang="matlab">
 
function gzoom(n, f)
 
% gzoom.m
 
% Michael R. Gustafson II (mrg@duke.edu)
 
% Uploaded to pundit.pratt.duke.edu on September 6, 2008
 
%
 
% Function to determine the size of a figure window and increase the size
 
% GZOOM will increase figure 1 by a factor of
 
%      0.1 of the original size in each direction
 
% GZOOM(r) will increase figure 1 by a factor of
 
%      r of the original size in each direction 
 
% GZOOM(r, f) will increase figure f by a factor of
 
%      r of the original size in each direction
 
  
if nargin==0
 
    f=gca; n=0.1;
 
elseif nargin==1
 
    f=gca;
 
end
 
v=axis;
 
xr = (v(2)-v(1));
 
yr = (v(4)-v(3));
 
axis(f, [v + n*[-xr xr -yr yr]]);
 
</source>
 
  
 
== Using Different Line Styles ==
 
== Using Different Line Styles ==
Most of the time, you will be plotting three or fewer different lines on a single window, and they can thus be distinguished from one another in [[MATLAB]] by using different line styles.  There are two different ways to get multiple data sets plotted in the same figure - use the <code>hold on</code>...<code>hold off</code> paradigm or put all the "plot triplets" in a single plot command.  What follows is an example of the latter case:
+
Most of the time, you will be plotting three or fewer different lines on a single window, and they can thus be distinguished from one another in [[Python]] by using different line styles.   
<source lang="matlab">
+
<source lang="python">
x = linspace(0, 1, 100);
+
x = np.linspace(0, 1, 100)
y1 = x.^0.5;
+
y1 = x**0.5
y2 = x.^1;
+
y2 = x**1
y3 = x.^2;
+
y3 = x**2
plot(x, y1, 'k-', x, y2, 'k--', x, y3, 'k:');
+
plt.figure(1)
legend('y=x^{0.5}', 'y=x', 'y=x^2', 'location', 'best');
+
plt.clf()
title('y=x^n for Three Values of n (mrg)');
+
plt.plot(x, y1, 'k-', label='$y=x^{0.5}$')
xlabel('x');
+
plt.plot(x, y2, 'k--', label='$y=x$')
ylabel('y');
+
plt.plot(x, y3, 'k:', label='$y=x^2$')
print -deps CurvePlot % note that adds .eps to filename
+
plt.legend(loc='best');
 +
plt.title('$y=x^n$ for Three Values of n (mrg)')
 +
plt.xlabel('x')
 +
plt.ylabel('y')
 +
plt.savefig('CurvePlotPython.png')
 
</source>
 
</source>
 
The figure this creates will be:
 
The figure this creates will be:
 
<center>
 
<center>
[[Image:CurvePlot.png]]
+
[[Image:CurvePlotPython.png]]
 
</center>
 
</center>
Note the legend - the use of the final arguments ''' 'location', 'best' ''' will make MATLAB look for the best spot in the window for the legend - which is to say, somewhere ''not'' conflicting with any of the lines if at all possibleAlso note that the text in the legend and in the title contains basic [[LaTeX]] code for obtaining the superscripts.
+
Note the legend command argument.  The default location is upper right but that may land on the data.  Telling it to use the best location will have Python look for the most-blank part of the plotThere are many other options for location - try <code>help(plt.legend)</code> and look at the section about <code>loc</code> in the Other Parameters.
  
 
== Using Different Point Styles ==
 
== Using Different Point Styles ==
Sometimes there will be more data sets on a graph than there are line styles in MATLAB.   
+
Sometimes there will be more data sets on a graph than there are line styles in Python.   
 
In cases like this, you may think to use symbols at the
 
In cases like this, you may think to use symbols at the
 
points.  The problem with that becomes clear if you have a large number of data points -  
 
points.  The problem with that becomes clear if you have a large number of data points -  
Line 386: Line 356:
 
both graphs in the figure is given below it.
 
both graphs in the figure is given below it.
 
<center>
 
<center>
[[Image:Deccurves.png]]
+
[[Image:DeccurvesPython.png]]
 
</center>
 
</center>
  
<source lang="matlab">
+
<source lang="python">
x = linspace(0, 1, 100);
+
x = np.linspace(0, 1, 100)
y1 = x.^0.5;
+
y1 = x**0.5
y2 = x.^1;
+
y2 = x**1
y3 = x.^2;
+
y3 = x**2
subplot(1,2,1) % left graph (ewwwwwww)
+
plt.figure(1)
plot(x, y1, 'k-s', x, y2, 'k-o', x, y3, 'k-p');
+
plt.clf()
legend('y=x^{0.5}', 'y=x', 'y=x^2', 'location', 'best');
+
plt.subplot(1,2,1) # left graph (ewwwwwww)
title('y=x^n for Three Values of n (mrg)');
+
plt.plot(x, y1, 'k-s', x, y2, 'k-o', x, y3, 'k-d')
xlabel('x');
+
plt.legend(['y=x^{0.5}', 'y=x', 'y=x^2'], loc='best')
ylabel('y');
+
 
 +
plt.title('Three Power Curves (mrg)')
 +
plt.xlabel('x')
 +
plt.ylabel('y')
  
subplot(1,2,2) % right graph (ooo.  aah.  wow)
+
plt.subplot(1,2,2) # right graph (ooo.  aah.  wow)
plot(x, y1, 'k-', x, y2, 'k-', x, y3, 'k-'); % lines only!
+
plt.plot(x, y1, 'k-', x, y2, 'k-', x, y3, 'k-') # lines only!
Incr = 5;
+
Incr = 10;
Indices = 1:Incr:length(x);
+
 
hold on % holds lines and now add points
+
PointPlot=plt.plot(
PointPlot=plot(...
+
     x[1::Incr], y1[1::Incr], 'ks',
     x(Indices), y1(Indices), 'ks',...
+
     x[1::Incr], y2[1::Incr], 'ko',
     x(Indices), y2(Indices), 'ko',...
+
     x[1::Incr], y3[1::Incr], 'kd')
     x(Indices), y3(Indices), 'kp');
+
plt.legend(PointPlot, ['y=x^{0.5}', 'y=x', 'y=x^2']loc='best')
hold off
+
plt.title('Three Power Curves (mrg)')
legend(PointPlot, 'y=x^{0.5}', 'y=x', 'y=x^2',  'location', 'best');
+
plt.xlabel('x')
title('y=x^n for Three Values of n (mrg)');
+
plt.ylabel('y')
xlabel('x');
+
plt.savefig('DeccurvesPython.png')
ylabel('y');
 
 
</source>
 
</source>
  
Line 424: Line 396:
  
 
== Using Different Scales ==
 
== Using Different Scales ==
In the above example, two different scales were used for the data sets - a refined scale for the line and a rougher scale for the data points themselves.  In other cases, it is the ''line'' that will need the rougher scale.  As an example, assume you want MATLAB to numerically find the minimum of the function <math>y=3x^2+11x-2</math> using the built-in <code>min</code> command.  To get the most precise answer possible, you will want to give MATLAB a very large number of points - say, 1 million.  That code might look like:
+
In the above example, two different scales were used for the data sets - a refined scale for the line and a rougher scale for the data points themselves.  In other cases, it is the ''line'' that will need the rougher scale.  As an example, assume you want Python to numerically find the minimum of the function <math>y=3x^2+11x-2</math> using the built-in <code>min</code> command.  To get the most precise answer possible, you will want to give Python a very large number of points - say, 1 million.  That code might look like:
<source lang="matlab">
+
<source lang="Python">
P = [3 11 -2]
+
P = [3, 11, -2]
xVals = linspace(-3, 3, 1e6);
+
xVals = np.linspace(-3.0, 3.0, int(1e6))
yVals = polyval(P, xVals);
+
yVals = np.polyval(P, xVals)
 
yMin = min(yVals)
 
yMin = min(yVals)
xMin = xVals(find(yVals==yMin))
+
xMin = xVals[np.where(yVals==yMin)]
 +
print(xMin, yMin)
 
</source>
 
</source>
Since the domain is 6 and there are 1e6 points, the spacing between points is approximately 6e-06.  The ''x''-coordinate of the answer then should be very close to the actual answer.  In fact, MATLAB determines that the minimum value is -1.208333333332658e+01 and its ''x''-coordinate is -1.833334833334833e+00 - very close to finding the minimum of ''y''=-1.208333333333333e+01 at  ''x''=-1.833333333333333e+00
+
Since the domain is 6 and there are 1e6 points, the spacing between points is approximately 6e-06.  The ''x''-coordinate of the answer then should be very close to the actual answer.  In fact, Python determines that the minimum value is -1.208333333332658e+01 and its ''x''-coordinate is -1.833334833334833e+00 - very close to finding the minimum of ''y''=-1.208333333333333e+01 at  ''x''=-1.833333333333333e+00
  
 
The problem, however, is that if you want to graph this, one million points is somewhat absurd.  Unless you are planning to zoom in on the graph, there are around 1000x as many points as necessary/realistic/useful for a plot like this.  Instead, you should either recalculate the equation using a smaller set of independent data or plot only some of the data.  Code for the former might be:
 
The problem, however, is that if you want to graph this, one million points is somewhat absurd.  Unless you are planning to zoom in on the graph, there are around 1000x as many points as necessary/realistic/useful for a plot like this.  Instead, you should either recalculate the equation using a smaller set of independent data or plot only some of the data.  Code for the former might be:
<source lang="matlab">
+
<source lang="python">
xPlot = linspace(-3, 3, 100);
+
xPlot = np.linspace(-3, 3, 100)
yPlot = polyval(P, xPlot);
+
yPlot = np.polyval(P, xPlot)
plot(xPlot, yPlot, 'k-');
+
plt.plot(xPlot, yPlot, 'k-')
xlabel('x');
+
plt.xlabel('x')
ylabel('y');
+
plt.ylabel('y')
title('y=3x^2+11x-2 (mrg)');
+
plt.title('$y=3x^2+11x-2$ (mrg)')
grid on
+
plt.grid(1)
print -deps PolyGraph
 
 
</source>
 
</source>
 
while code for the latter might be:
 
while code for the latter might be:
<source lang="matlab">
+
<source lang="python">
plot(xVals(1:1000:end), yVals(1:1000:end), 'k-');
+
plt.plot(xVals[1::1000], yVals[1::1000], 'k-');
xlabel('x');
+
plt.xlabel('x');
ylabel('y');
+
plt.ylabel('y');
title('y=3x^2+11x-2 (mrg)');
+
plt.title('$y=3x^2+11x-2$ (mrg)');
grid on
+
plt.grid(1)
print -deps PolyGraph
 
 
</source>
 
</source>
  
Line 466: Line 437:
  
 
First, the text command will ''not'' make the figure change its axes  
 
First, the text command will ''not'' make the figure change its axes  
to fit the data automatically.  Clear the figure using <code>clf</code> then  try typing:
+
to fit the data automatically.  Clear the figure using <code>plt.clf()</code> then  try typing:
<source lang="matlab">
+
<source lang="python">
text([1; 2; 3], [1; 2; 3], ['a'; 'b'; 'c']);
+
plt.text(2, 2, 'Hi')
 
</source>
 
</source>
and you will get the graph:
+
The figure will show the word Hi in the top right but it will not be in the axis limits.
<center>
+
You need to change the axis limits by using the <code>axis</code> command.  In this case,
[[Image:Text1.png|400px]]
+
<source lang="python">
</center>
+
plt.axis((0, 3, 1, 4))
Note that the letter <code>a</code> is just visible at the top right corner
+
plt.text(2, 3, 'Hi')
but <code>b</code> and <code>c</code>are totally missing. You need to manually
 
changes the axes by using the <code>axis</code> command.  In this case,
 
<source lang="matlab">
 
axis([0 4 -1 5])
 
 
</source>
 
</source>
will make the ''x'' axis go from 0 to 4 and the ''y''
+
will make the ''x'' axis go from 0 to 3 and the ''y''
axis go from -1 to 5, more than enough space to see all three letters:
+
axis go from 1 to 4, more than enough space to say "Hi" at (2,3)!
<center>
 
[[Image:Text2.png|400px]]
 
</center>
 
  
 
Next, note that  
 
Next, note that  
 
text placed on plots stays until the next plotting command is
 
text placed on plots stays until the next plotting command is
issued, so you can use multiple <code>text</code> commands to get several
+
issued, so you can use multiple <code>plt.text</code> commands to get several
labels on one plot.  Also, the arguments can be column vectors which
+
labels on one plot.   
allows multiple labels to be added at once (such as in the above
 
example).  Note that <code>row vectors</code> do not work.  Clear the figure
 
using <code>clf</code> then try the following:
 
<source lang="matlab">
 
text([1 2 3], [1 2 3], ['a' 'b' 'c']);
 
axis([0 4 -1 5]);
 
</source>
 
This gives you:
 
<center>
 
[[Image:Text3.png|400px]]
 
</center>
 
Because you gave rows of labels instead of columns, <code>text</code> puts the
 
letters <code>abc</code> at each data point.  In this case, you can solve the problem by transposing the third argument.
 
 
 
Also, the text must be...text.  If you try to label using numbers you
 
will get an error.  Try
 
<source lang="matlab">
 
text([1; 2; 3], [1; 2; 3], [1; 2; 3]);
 
axis([0 4 -1 5]);
 
</source>
 
Fortunately, MATLAB has a command called <code>num2str</code> that will
 
convert numbers to strings.  Clear the figure and try
 
<source lang="matlab">
 
text([1; 2; 3], [1; 2; 3], num2str([1; 2; 3]));
 
axis([0 4 -1 5]);
 
</source>
 
and you will get
 
<center>
 
[[Image:Text4.png|400px]]
 
</center>
 
 
 
Finally, if you put multiple pieces of text on at once, they must all be
 
the same size.  You can ensure that they are by using the <code>char</code> command.  Clear the figure and try:
 
<source lang="matlab">
 
text([1; 2; 3], [1; 2; 3], char('one', 'two', 'three'))
 
axis([0 4 -1 5]);
 
</source>
 
The <code>char</code> command will automatically pad the shorter words with spaces, and the <code>text</code> command will give you:
 
<center>
 
[[Image:Text5.png|400px]]
 
</center>
 
  
 +
<!--
 
== Setting Limits and Tick Locations ==
 
== Setting Limits and Tick Locations ==
 
[[File:PalmFig050204plot.png|thumb|300px]]You can set the specific limits and tick locations for a graph such that they will not change when you resize the figure window and so that they print exactly as you see on the screen.  To do this, you will use the <code>set</code> command with some specific arguments. The following example is modified from Palm, Chapter 5.2, on page 231 to create the specific figure as shown in the book:
 
[[File:PalmFig050204plot.png|thumb|300px]]You can set the specific limits and tick locations for a graph such that they will not change when you resize the figure window and so that they print exactly as you see on the screen.  To do this, you will use the <code>set</code> command with some specific arguments. The following example is modified from Palm, Chapter 5.2, on page 231 to create the specific figure as shown in the book:
  
<source lang=matlab>
+
<source lang=python>
 
% Code based on code from:  
 
% Code based on code from:  
 
% Palm, Introduction to MATLAB for Engineers
 
% Palm, Introduction to MATLAB for Engineers

Revision as of 23:36, 5 September 2018

This page will primarily go over some examples of different ways to plot data sets. It assumes

import math as m
import numpy as np
import matplotlib.pyplot as plt

is in the program.

Introduction

The plt.plot() Function

The plt.plot() function is used to plot sets of data on a 2-D grid. What follows comes from matplotlib.pyplot's help function (some paragraphs have been snipped out). The line styles, symbols, and colors are formatted as a clearer table.

plot(*args, **kwargs)
    Plot lines and/or markers to the
    :class:`~matplotlib.axes.Axes`.  *args* is a variable length
    argument, allowing for multiple *x*, *y* pairs with an
    optional format string.  For example, each of the following is
    legal::
    
        plot(x, y)        # plot x and y using default line style and color
        plot(x, y, 'bo')  # plot x and y using blue circle markers
        plot(y)           # plot y using x as index array 0..N-1
        plot(y, 'r+')     # ditto, but with red plusses
    
    If *x* and/or *y* is 2-dimensional, then the corresponding columns
    will be plotted.
    
    If used with labeled data, make sure that the color spec is not
    included as an element in data, as otherwise the last case
    ``plot("v","r", data={"v":..., "r":...)``
    can be interpreted as the first case which would do ``plot(v, r)``
    using the default line style and color.
    
    If not used with labeled data (i.e., without a data argument),
    an arbitrary number of *x*, *y*, *fmt* groups can be specified, as in::
    
        a.plot(x1, y1, 'g^', x2, y2, 'g-')
    
    Return value is a list of lines that were added.
    
    By default, each line is assigned a different style specified by a
    'style cycle'.  To change this behavior, you can edit the
    axes.prop_cycle rcParam.
    
    The following format string characters are accepted to control
    the line style or marker (and) the following color abbreviations are supported:
Line code Meaning
- solid
: dotted
-. dash-dot
-- dashed
Symbol code Meaning Symbol code Meaning
. point s square
, pixel p pentagon
o circle * star
v triangle (down) h hexagon 1
^ triangle (up) H hexagon 2
< triangle (left) + plus
> triangle (right) x x-mark
1 tri (down) D diamond
2 tri (up) d thin diamond
3 tri (left) vline
4 tri (right) _ hline
Color code Meaning
b blue
g green
r red
c cyan
m magenta
y yellow
k black
w white
    
    In addition, you can specify colors in many weird and
    wonderful ways, including full names (``'green'``), hex
    strings (``'#008000'``), RGB or RGBA tuples (``(0,1,0,1)``) or
    grayscale intensities as a string (``'0.8'``).  Of these, the
    string specifications can be used in place of a ``fmt`` group,
    but the tuple forms can be used only as ``kwargs``.
    
    Line styles and colors are combined in a single format string, as in
    ``'bo'`` for blue circles.
    
    The *kwargs* can be used to set line properties (any property that has
    a ``set_*`` method).  You can use this to set a line label (for auto
    legends), linewidth, anitialising, marker face color, etc.  Here is an
    example::
    
        plot([1,2,3], [1,2,3], 'go-', label='line 1', linewidth=2)
        plot([1,2,3], [1,4,9], 'rs',  label='line 2')
        axis([0, 4, 0, 10])
        legend()
    
    If you make multiple lines with one plot command, the kwargs
    apply to all those lines, e.g.::
    
        plot(x1, y1, x2, y2, antialiased=False)
    
    Neither line will be antialiased.
    
    You do not need to use format strings, which are just
    abbreviations.  All of the line properties can be controlled
    by keyword arguments.  For example, you can set the color,
    marker, linestyle, and markercolor with::
    
        plot(x, y, color='green', linestyle='dashed', marker='o',
             markerfacecolor='blue', markersize=12).


The plt.savefig() Function

The plt.savefig() function is used to save a plot to a file. The type of sile is determined by the extension of the file name. For example,

plt.savefig('blah.eps')

will save the file to a color Encapsulated PostScript file, while

plt.savefig('blah.pdf')

will save it to a PDF. From the help file for the command, Most backends support png, pdf, ps, eps and svg.

Example

Example showing a figure split into 2x3 subplots with subplot 3 holding an empty axis and subplot 4 holding a graph of the unit step function.

The following Python code demonstrates how to fill the fourth window of a 2x3 plot figure and save the figure as a PNG file; the resulting figure is in the thumbnail at right.

# Import required modules
import numpy as np
import matplotlib.pyplot as plt

# Create a 100 numbers between -1 and 1
x = np.linspace(-1, 1, 100); 

# This formula for usf is one of several ways to define the unit step function
def usf(t):
    return (t>=0)*1.0; 

# Create a figure with two rows of three figures and make subplot 4 (bottom row left) current
plt.figure(1)
plt.clf()
plt.subplot(2, 3, 4)

# Plot the values of the function usf(x) against the vector x
plt.plot(x, usf(x)) 

# Change the axes so the function is not covered by the subplot box
plt.axis([-1, 1, -1, 2])

# Give the current subplot a title
plt.title('Unit Step Function')

# Set the x-label
plt.xlabel('x')

# Set the y-label
plt.ylabel('u(x)')

# Make subplot 3 (top row right) current - it will be empty in the example
plt.subplot(2,3,3) 

# Send the current figure to a file named usfplot.png
plt.savefig('usfplot.png')

General Plotting Tips

You must make sure that your data sets are presented properly. Here are some guidelines:

  • Include axis labels that have, when appropriate, units. You should also include a description of the variable, or the variable itself, or both. For example, on p. 285 of Chapra[1], there is a plot of force versus velocity. Appropriate x axis labels would include any of the following:
plt.xlabel('$v$, m/s')
plt.xlabel('$v$ (m/s)')
plt.xlabel('Velocity, m/s')
plt.xlabel('Velocity (m/s)')
plt.xlabel('Velocity ($v$), m/s');
plt.xlabel('Velocity ($v$, m/s)');
You should be consistent within a single graph as far as which version you use, and you should pick which format you believe conveys the information most efficiently and effectively.
  • Make sure your titles make sense and that you have your NetID in one of the titles for each figure you create. If you have multiple subplots, you only need one of the titles to have your NetID. Typically, the title will read "DEP. VAR vs. INDEP. VAR for DESCRIPTION (NetID)" where DEP. VAR is your dependent variable (typically on the y axis), INDEP. VAR is your independent variable (typically on the x axis), DESCRIPTION is something that will differentiation this particular plot from others that might have the same variables (for example a data, or an experiment number), and NetID is your NetID.
  • Data points should be represented by symbols and model equations should be represented by lines. Be sure to use a legend to identify each item plotted if there are multiple data sets on the same graph.
  • Typically, you will want to set the axis limits such that no data point is on the figure boundary. Certainly you do not want a line to be plotted on top of a figure boundary. After you make a plot, if there is a data point on an edge, look at the current axes and go out a little bit. Just make sure if you end up fundamentally changing your code that you adjust the axes accordingly.


Using Different Line Styles

Most of the time, you will be plotting three or fewer different lines on a single window, and they can thus be distinguished from one another in Python by using different line styles.

x = np.linspace(0, 1, 100)
y1 = x**0.5
y2 = x**1
y3 = x**2
plt.figure(1)
plt.clf()
plt.plot(x, y1, 'k-', label='$y=x^{0.5}$')
plt.plot(x, y2, 'k--', label='$y=x$')
plt.plot(x, y3, 'k:', label='$y=x^2$')
plt.legend(loc='best');
plt.title('$y=x^n$ for Three Values of n (mrg)')
plt.xlabel('x')
plt.ylabel('y')
plt.savefig('CurvePlotPython.png')

The figure this creates will be:

CurvePlotPython.png

Note the legend command argument. The default location is upper right but that may land on the data. Telling it to use the best location will have Python look for the most-blank part of the plot. There are many other options for location - try help(plt.legend) and look at the section about loc in the Other Parameters.

Using Different Point Styles

Sometimes there will be more data sets on a graph than there are line styles in Python. In cases like this, you may think to use symbols at the points. The problem with that becomes clear if you have a large number of data points - you do not want to try to jam hundreds of symbols onto a curve. The left graph in the figure below shows what a disaster that could be. Instead, you can plot a line with all your data but plot points on top of the line with only some of the data. The right side of the figure shows the result of this operation. The code for both graphs in the figure is given below it.

DeccurvesPython.png

x = np.linspace(0, 1, 100)
y1 = x**0.5
y2 = x**1
y3 = x**2
plt.figure(1)
plt.clf()
plt.subplot(1,2,1) # left graph (ewwwwwww)
plt.plot(x, y1, 'k-s', x, y2, 'k-o', x, y3, 'k-d')
plt.legend(['y=x^{0.5}', 'y=x', 'y=x^2'], loc='best')

plt.title('Three Power Curves (mrg)')
plt.xlabel('x')
plt.ylabel('y')

plt.subplot(1,2,2) # right graph (ooo.  aah.  wow)
plt.plot(x, y1, 'k-', x, y2, 'k-', x, y3, 'k-') # lines only!
Incr = 10;

PointPlot=plt.plot(
    x[1::Incr], y1[1::Incr], 'ks',
    x[1::Incr], y2[1::Incr], 'ko',
    x[1::Incr], y3[1::Incr], 'kd')
plt.legend(PointPlot, ['y=x^{0.5}', 'y=x', 'y=x^2'],  loc='best')
plt.title('Three Power Curves (mrg)')
plt.xlabel('x')
plt.ylabel('y')
plt.savefig('DeccurvesPython.png')

Note that the assignment of one of the plots to the variable PointPlot is required so that the legend can be told which set of plots to use as a basis for the legend. Without this, it would be possible for the legend to be based on the plot using solid lines (which are the same for all three data sets) rather than to be based on the plot using the symbols.

Using Different Scales

In the above example, two different scales were used for the data sets - a refined scale for the line and a rougher scale for the data points themselves. In other cases, it is the line that will need the rougher scale. As an example, assume you want Python to numerically find the minimum of the function \(y=3x^2+11x-2\) using the built-in min command. To get the most precise answer possible, you will want to give Python a very large number of points - say, 1 million. That code might look like:

P = [3, 11, -2]
xVals = np.linspace(-3.0, 3.0, int(1e6))
yVals = np.polyval(P, xVals)
yMin = min(yVals)
xMin = xVals[np.where(yVals==yMin)]
print(xMin, yMin)

Since the domain is 6 and there are 1e6 points, the spacing between points is approximately 6e-06. The x-coordinate of the answer then should be very close to the actual answer. In fact, Python determines that the minimum value is -1.208333333332658e+01 and its x-coordinate is -1.833334833334833e+00 - very close to finding the minimum of y=-1.208333333333333e+01 at x=-1.833333333333333e+00

The problem, however, is that if you want to graph this, one million points is somewhat absurd. Unless you are planning to zoom in on the graph, there are around 1000x as many points as necessary/realistic/useful for a plot like this. Instead, you should either recalculate the equation using a smaller set of independent data or plot only some of the data. Code for the former might be:

xPlot = np.linspace(-3, 3, 100)
yPlot = np.polyval(P, xPlot)
plt.plot(xPlot, yPlot, 'k-')
plt.xlabel('x')
plt.ylabel('y')
plt.title('$y=3x^2+11x-2$ (mrg)')
plt.grid(1)

while code for the latter might be:

plt.plot(xVals[1::1000], yVals[1::1000], 'k-');
plt.xlabel('x');
plt.ylabel('y');
plt.title('$y=3x^2+11x-2$ (mrg)');
plt.grid(1)

The advantage of the first version above is that your domain definitely remains the same - the xPlot variable spans the same [-3, 3] as the xVals set even though it has three orders of magnitude fewer values. The disadvantage is that you will have to re-perform all the calculations on this new set.

The advantage of the second version, then, is that you are using prior data and thus do not have to recalculate anything. The disadvantage is, you might miss out on the tail end of the data. In the above example, going from 1 to 1e6 by 1e3 means the last value copied over will be 999001, meaning the maximum value used on the x-axis is xVals(999001) or approximately 2.994 instead of the 3 in the original. If that is a major concern, you should make sure the end of your refined data scale can be "reached" if your incremented indices start with 1 and have some increment. As an example, choosing to have 1000001 points in the original instead of 1000000 means going from 1 by 1e3 to 10000001 will actually end at the 10000001st, and last, point.

Putting Text on a Plot

The text(x, y, MyText) command will plot the text string MyText at the (x,y) coordinate. There are several important aspects to the text command you must remember to use it properly.

First, the text command will not make the figure change its axes to fit the data automatically. Clear the figure using plt.clf() then try typing:

plt.text(2, 2, 'Hi')

The figure will show the word Hi in the top right but it will not be in the axis limits. You need to change the axis limits by using the axis command. In this case,

plt.axis((0, 3, 1, 4))
plt.text(2, 3, 'Hi')

will make the x axis go from 0 to 3 and the y axis go from 1 to 4, more than enough space to say "Hi" at (2,3)!

Next, note that text placed on plots stays until the next plotting command is issued, so you can use multiple plt.text commands to get several labels on one plot.


Questions

Post your questions by editing the discussion page of this article. Edit the page, then scroll to the bottom and add a question by putting in the characters *{{Q}}, followed by your question and finally your signature (with four tildes, i.e. ~~~~). Using the {{Q}} will automatically put the page in the category of pages with questions - other editors hoping to help out can then go to that category page to see where the questions are. See the page for Template:Q for details and examples.

External Links

References