User Tools

Site Tools


pylabrecipes

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 Pylab Command Overview or the 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

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.

# 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 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 here

Choose good colormap (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 annotations to enrich your plots with additional information. More Code Samples 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 - 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 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 quick fix.

pylabrecipes.txt · Last modified: 2015/08/04 13:36 by mantis