Pylab is a procedural interface to the matplotlib object-oriented plotting library. It can be installed via apt:
sudo apt-get install python-matplotlib python-gtk2
To find out what you can do with it have a look at the [[http://matplotlib.sourceforge.net/pylab_commands.html|Pylab Command Overview]] or the [[http://matplotlib.sourceforge.net/|Matplotlib Site]]
====== Control axis ticks ======
by setting tick locations and tick labels
It is also possible to rotate long labels:
pylab.xticks( arange(12), calendar.month_name[1:13], rotation=17 )
====== Plots with date axes ======
Use pylab.plot_date and the boolean parameters xdate and ydate date2num takes datetime instance or a sequence of datetimes as parameter and converts it/them to float(s).
pylab.plot_date(dates,values, xdate=True, ydate=False)
====== Format Date Axes ======
To show hours on the X-Axis:
import pylab
from matplotlib.dates import DateFormatter,HourLocator
pylab.plot_date(pylab.date2num(times), values, "b-", xdate=True, ydate=False, label="memory use" )
axes=pylab.gca()
# Display the time of day every 2 hours
axes.xaxis.set_major_locator(HourLocator(interval=2))
axes.xaxis.set_major_formatter(DateFormatter('%H:%M'))
# Display a small tick every hour
axes.xaxis.set_minor_locator(HourLocator())
To show days on the X-Axis.
import pylab
from matplotlib.dates import DateFormatter,DayLocator, HourLocator
pylab.plot_date(times,values) # plot data
# Display date at beginning of each day
pylab.gca().xaxis.set_major_locator(DayLocator())
pylab.gca().xaxis.set_major_formatter(DateFormatter('%d.%b %Y'))
# display a small tick every 6 hours
pylab.gca().xaxis.set_minor_locator(HourLocator(byhour=(0,6,12,18)))
====== Set Axis Min/Max ======
pylab.plot(values)
pylab.axis(ymax=100) # or ymin|xmax|xmin ( Note: its important to call pylab.axis() AFTER the plot command! ) pylab.show()
====== Change Font Size of Axis Labels ======
fontsize = 8
for tick in pylab.gca().xaxis.get_major_ticks():
tick.label1.set_fontsize(fontsize)
====== Plot lines ======
Draw a horizontal line at y=60 from xmin to xmax
pylab.axhline(60,color="g", linestyle="--", label="free speed")
====== Plot Histograms ======
n,bins,patches = pylab.hist(values, noOfBins)
====== Kernel Density ======
import pylab
import scipy
import numpy
# get data from somewhere
data = numpy.random.normal(0,1,1000)
# Important Note: Make sure your data is float. If your data is int it does not work for some reason!
# histogram of data
pylab.hist(data,50, normed=True)
# add kernel density plot with gaussian kernel
kernel = scipy.stats.kde.gaussian_kde(data)
ind = numpy.linspace(-5,5,100)
kdepdf = kernel.evaluate(ind)
pylab.plot(ind, kdepdf,'r',linewidth=2)
see
* http://jpktd.blogspot.com/2009/03/using-gaussian-kernel-density.html
* http://www.scipy.org/SciPyPackages/Stats
====== ECDF ======
import numpy
import statsmodels.distributions
ecdf = statsmodels.distributions.ECDF(data)
x = numpy.linspace(min(data), max(data))
y = ecdf(x)
pylab.plot(x,y) # or pylab.step(x, y)
====== Donut plot ======
Is (unsurprisingly) made from pie plots.
A very good example is here http://matplotlib.1069221.n5.nabble.com/how-to-draw-concentric-donuts-chart-tp43408p43412.html
I needed just a clean, simple "binary" donut, so I simplified that code.
{{:data.png?300|}}
# thanks to Joe Kington http://matplotlib.1069221.n5.nabble.com/how-to-draw-concentric-donuts-chart-tp43408p43412.html
def make_pie(percent, text):
import matplotlib.pyplot as plt
import numpy as np
c1 = '#9999FF'
c2 = '#FF9999'
fig, ax = plt.subplots()
ax.axis('equal')
width = 0.15
kwargs = dict(colors=[c1, c2], startangle=180, counterclock=False)
outside, _ = ax.pie([percent, 1-percent], radius=1, pctdistance=1-width/2, **kwargs)
plt.setp( outside, width=width, edgecolor='white')
kwargs = dict(size=20, fontweight='bold', va='center', color=c1)
ax.text(0, 0, "{0}% {1}".format(percent*100, text), ha='center', **kwargs)
plt.show()
make_pie(0.95, "of your data\n is made up")
====== Plot (stack) bars ======
Use pylab.bar to plot (stack) bars:
bar(left, height, width=0.8, bottom=0, color=None, edgecolor=None, linewidth=None, yerr=None, xerr=None, ecolor=None, capsize=3, align='edge', orientation='vertical', log=False)
#left - the x coordinates of the left sides of the bars
#height - the heights of the bars
#bottom - the y coordinates of the bottom edges of the bars
#xerr, yerr - use to generate errorbars on the bar chart
To plot stack bars use the argument "bottom", for example:
width=0.8 heights1 = (20, 35, 30, 35, 27) #heights of bar1
heights2 = (25, 32, 34, 20, 25) #heights of bar2
bar1 = pylab.bar(arange(5), heights1, width, color='r')
bar2 = pylab.bar(arange(5), heights2, width, color='y', bottom=heights1)
====== Rotate xticklabels to vertical ======
labels = pylab.getp(pylab.gca(),'xticklabels') # getproperty xticklabels from current axes
pylab.setp(labels, rotation='vertical')
====== Add text ======
Add text in string s to axis at location x,y (default: data coords). It is also possible to specify text in axis coords (0,0 lower left and 1,1 upper right).
text(x, y, s, fontsize=12)
====== Add text with Umlauts ======
text(x, y, unicode('hübsche Umlaute: ä ü ö', 'latin-1'))
====== Draw colored area / belt ("band") ======
To draw a belt do:
pylab.fill_between(x,ylower, yupper, color='blue', alpha=0.1)
====== Mark/colour/paint areas ======
check [[http://matplotlib.sourceforge.net/examples/pylab_examples/axhspan_demo.html this example]] to see how it looks like.
eg. to mark months in a plot:
# get day of the year
aug=int(datetime(2008,8,1).strftime("%j"))
sept=int(datetime(2008,9,1).strftime("%j"))
okt=int(datetime(2008,10,1).strftime("%j"))
nov=int(datetime(2008,11,1).strftime("%j"))
# plot areas
subplot.axvspan(aug-0.5, sept-0.5, facecolor='0.5', alpha=0.2)
subplot.axvspan(okt-0.5, nov-0.5, facecolor='0.5', alpha=0.2) # add descriptive text
subplot.text( aug, 13500, 'August')
subplot.text( sept, 13500, 'September')
subplot.text( okt, 13500, 'October') ''
also works horizontally using:
subplot.axhspan(ymin,ymax)
====== Legends ======
===== Add legend =====
In order to display a lagend you need to label your plots. For example
pylab.plot_date(pylab.date2num(dates),speeds,"b-", xdate=True, ydate=False, label="taxi speeds") # the plot should be named "taxi speeds" in the legend
pylab.legend() # add the legend to the plot pylab.show() ''
===== Legends outside of plot =====
Often there simply is no room to put the legend inside a plot. There are several approaches to put it partly or completely outside the plot.
This [[http://stackoverflow.com/questions/4700614/how-to-put-the-legend-out-of-the-plot|stackoverflow]] thread shows how to use the bbox_to_anchor keyword to move the legend partly outside the plot:
ax = plt.subplot(111)
#ax.plot(something)
ax.legend(bbox_to_anchor=(1.1, 1.05))
Alternatively the thread show how to shrink the current plot's width: this gains some space outside the plot where the legend can be put.
ax = plt.subplot(111)
#ax.plot(plot something)
# Shink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
# Put a legend to the right of the current axis
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
===== Font properties of legends =====
Sometimes simply shrinking the legend font helps to improve the visibility of data in a plot:
from matplotlib.font_manager import FontProperties
fontP = FontProperties()
fontP.set_size('xx-small')
legend([plot1], "title", prop = fontP)
====== Save Figure ======
pylab.plot(...)
pylab.savefig("my_figure.png", format="png")
====== Subplots ======
To create a subplot with 2 lines, and 1 Column, and switch to the first image:
pylab.subplot(211)
# plot first chart...
# now switch to the second image
pylab.subplot(212)
# plot second chart
====== Using Pylab in CGI Scripts ======
Its necessary to do a few things before importing the pylab module:
import os os.environ[ 'HOME' ] = '/tmp/'#set HOME environment variable to a directory the httpd server can write to
import matplotlib
matplotlib.use( 'Agg' )#use a non-gui backend.
# Now pylab can be imported without errors
import pylab
import sys
#Create your plot like you normally would, then return it to the browser by doing the following:
print "Content-Type: image/png\n"
pylab.savefig(sys.stdout, format='png' )
====== Adding color to plots ======
from random import choice
colors = ['#FFFFCC','#FFFF99','#FFFF66','#FFFF33','#FFFF00','#FFCCFF','#FFCCCC','#FFCC99','#FFCC66','#FFCC33','#FFCC00','#FF99FF','#FF99CC','#FF9999','#FF9966','#FF9933','#FF9900','#FF66FF','#FF66CC','#FF6699','#FF6666','#FF6633','#FF6600','#FF33FF','#FF33CC','#FF3399','#FF3366','#FF3333','#FF3300','#FF00FF','#FF00CC','#FF0099','#FF0066','#FF0033','#FF0000','#CCFFFF','#CCFFCC','#CCFF99','#CCFF66','#CCFF33','#CCFF00','#CCCCFF','#CCCCCC','#CCCC99','#CCCC66','#CCCC33','#CCCC00','#CC99FF','#CC99CC','#CC9999','#CC9966','#CC9933','#CC9900','#CC66FF','#CC66CC','#CC6699','#CC6666','#CC6633','#CC6600','#CC33FF','#CC33CC','#CC3399','#CC3366','#CC3333','#CC3300','#CC00FF','#CC00CC','#CC0099','#CC0066','#CC0033','#CC0000','#99FFFF','#99FFCC','#99FF99','#99FF66','#99FF33','#99FF00','#99CCFF','#99CCCC','#99CC99','#99CC66','#99CC33','#99CC00','#9999FF','#9999CC','#999999','#999966','#999933','#999900','#9966FF','#9966CC','#996699','#996666','#996633','#996600','#9933FF','#9933CC','#993399','#993366','#993333','#993300','#9900FF','#9900CC','#990099','#990066','#990033','#990000','#66FFFF','#66FFCC','#66FF99','#66FF66','#66FF33','#66FF00','#66CCFF','#66CCCC','#66CC99','#66CC66','#66CC33','#66CC00','#6699FF','#6699CC','#669999','#669966','#669933','#669900','#6666FF','#6666CC','#666699','#666666','#666633','#666600','#6633FF','#6633CC','#663399','#663366','#663333','#663300','#6600FF','#6600CC','#660099','#660066','#660033','#660000','#33FFFF','#33FFCC','#33FF99','#33FF66','#33FF33','#33FF00','#33CCFF','#33CCCC','#33CC99','#33CC66','#33CC33','#33CC00','#3399FF','#3399CC','#339999','#339966','#339933','#339900','#3366FF','#3366CC','#336699','#336666','#336633','#336600','#3333FF','#3333CC','#333399','#333366','#333333','#333300','#3300FF','#3300CC','#330099','#330066','#330033','#330000','#00FFFF','#00FFCC','#00FF99','#00FF66','#00FF33','#00FF00','#00CCFF','#00CCCC','#00CC99','#00CC66','#00CC33','#00CC00','#0099FF','#0099CC','#009999','#009966','#009933','#009900','#0066FF','#0066CC','#006699','#006666','#006633','#006600','#0033FF','#0033CC','#003399','#003366','#003333','#003300','#0000FF','#0000CC','#000099','#000066','#000033','#000000']
pylab.bar(h, prev, width,color=choice(colors))
====== Selecting color from colormaps ======
Found [[https://geetduggal.wordpress.com/2011/08/22/grabbing-individual-colors-from-color-maps-in-matplotlib/|here]]
Choose good colormap ([[http://matplotlib.org/examples/color/colormaps_reference.html|reference]]) and call it as function with a parameter between 0 and 1
import pylab as p
c1 = p.cm.gnuplot2(0.3)
c2 = p.cm.gnuplot2(0.7)
p.plot(range(0, 5), color=c1)
p.plot(range(4, 9), color=c2)
p.show()
====== Make "customised" legends ======
Not very elegant but googling helped me doing the job: these lines are never plotted, only used for building a legend.
from matplotlib.lines
import Line2D
line0 = Line2D(range(1), range(1), lw=4,color='darkgreen' )
line1 = Line2D(range(1), range(1), lw=4,color='skyblue' )
pylab.legend((line0,line1),('weekdays','weekends'),loc='best')
====== Show legend outside plot ======
import pylab
pylab.figure()
pylab.subplot(111)
pylab.subplots_adjust(right=0.7)
pylab.plot([1,6,11],label="1) label very long")
pylab.plot([2,6,10],label="2) label") #Legende 1,1: ausrichtung rechts neben der Grafik; 0,1 unten neben der Grafik beginnen
pylab.legend(loc=(1.1,0.1)) #show legend on the right side of the chart
pylab.show()
====== Axis Labels ======
import pylab
pylab.plot(....)
pylab.axes().set_xlabel("hour")
pylab.axes().set_ylabel("speed")
====== Format axes ======
import pylab
pylab.figure()
pylab.axes([0.1,0.1,0.71,0.8])
pylab.plot([0,1],[0,1],label="line 1")
pylab.hold(1) pylab.plot([0,1],[1,0.5],label="line 2")
pylab.legend(loc=(1.03,0.2))
pylab.show()
====== Overwrite Legend Function ======
Function for overwriting:
def legend(*args, **kwargs):
""" Overwrites the pylab legend function. It adds another location identfier 'outer right' which locates the legend on the right side of the plot The args and kwargs are forwarded to the pylab legend function """
if kwargs.has_key('loc'):
loc = kwargs['loc']
loc = loc.split()
if loc[0] == 'outer':
# make a legend with out the location
kwargs.pop('loc') # remove the location setting from the kwargs
leg = pylab.legend(loc=(0,0), *args, **kwargs)
frame = leg.get_frame()
currentAxes = pylab.gca()
currentAxesPos = currentAxes.get_position() # scale plot by the part which is taken by the legend
plotScaling = frame.get_width()/currentAxesPos[2]
if loc[1] == 'right':
# scale the plot
currentAxes.set_position((currentAxesPos[0],currentAxesPos[1],currentAxesPos[2]*(1-plotScaling),currentAxesPos[3])) # set x and y coordinates of legend.
leg._loc = (1 + leg.axespad, 1 - frame.get_height())
pylab.draw_if_interactive()
return leg
return pylab.legend(*args, **kwargs) ''
Test the function:
pylab.plot([1,6,11],label="1) label")
pylab.plot([2,6,10],label="2) label")
pylab.plot([3,6,9],label ="3) label")
pylab.plot([4,6,8],label ="4) label")
pylab.title("Legend override (outer right)")
pylab.grid()
legend(loc='outer right')
pylab.show()
source: : http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg04256.html
====== Annotations ======
Use [[http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.annotate|annotations]] to enrich your plots with additional information. More Code Samples [[http://matplotlib.sourceforge.net/examples/pylab_examples/annotation_demo2.html|here]]]
====== Continuously updating a plot ======
The easy (but grossly inefficient) way:
import pylab
import time
import random
x=[]
pylab.figure(1)
pylab.subplot(111)
for i in range (50):
x.append(random.randint(0,100))
pylab.cla()
pylab.plot(x)
time.sleep(1)
====== Contour Plot ======
===== Save Contour Plot as MIF =====
Here is a small function to save a contour plot as a MIF File (so it can be displayed in QGis etc.)
import numpy.random
import pylab
def saveAsMIF(contour_plot, filename):
coll = contour_plot.collections
mid=file("%s.mid" %filename, "w")
mif=file("%s.mif"%filename, "w")
mif.write("""Version 300\nCharset "WindowsLatin1"\nDelimiter ","\nCOLUMNS 1\nLevel Integer\n""")
mif.write("""DATA\n""")
for level in range(0,len(coll)):
for path in coll[level].get_paths():
polygon = path.to_polygons()[0]
mif.write("PLINE %d\n" % len(polygon))
for c in polygon:
mif.write("%f %f\n" % (c[0], c[1]) )
mid.write('"%d""\n' % level )
mid.close()
mif.close()
# example
x=numpy.arange(100)/100.0 + 16.0
y=numpy.arange(100)/100.0 + 48.0
z= numpy.random.rand(100,100)
C=pylab.contour(x,y,z)
saveAsMIF(C,"test")
======= 3D plotting =======
3D support was dropped by matplotlib but there are alternatives. One is [[http://code.enthought.com/projects/mayavi/docs/development/html/mayavi/mlab.html Mayavi2's mlab API]].
sudo apt-get install mayavi2
Then you can use it in your python scripts
from enthought.mayavi
import mlab
======= Resize Figure =======
fig.set_size_inches(20,15,forward=True)
====== Multiple Y-Axes ======
fig = pylab.figure()
ax1 = fig.add_subplot(111)
# plot something on the first pair
ax1.plot(range(100))
ax1.axis(ymin=0, ymax=100) # set scale
# get a second pair of axes and plot something else
ax2 = ax1.twinx()
ax2.plot(range(100))
ax2.axis(ymin=0, ymax=1000)
====== ggplot ======
Pretty plots ahead - [[https://github.com/yhat/ggplot|ggplot]] is a port of R's ggplot2, has tight integration with pandas and is easy to install.
pip install ggplot
You can also use it to switch plot styles in [[http://matplotlib.org/users/style_sheets.html|matplotlib]]:
import matplotlib.pyplot as plt
plt.style.use('ggplot')
You need at least matplotlib 1.4.x, which might not be what your package provider offers. You can upgrade matplotlib with pip, but I ran into a quirk on Ubuntu 14.04 during installation. Here's a [[https://mlbernauer.wordpress.com/2014/12/06/upgrading-from-matplotlib-1-3-1-to-1-4-1-in-ubuntu-14-04/|quick fix]].