21
votes

I'm drawing several bar and pie charts using matplotlib.pyplot.bar() and matplotlib.pyplot.pie(). In both functions, I can change the colors of the bars and wedges.

However, I need to print these charts in black and white. It would be much more useful to be able to put textures on the bars and wedges, similar to the Line2D marker property which is available for drawing lines. Can I maybe fill the bars and wedges with these markers in a consistent way? Or is there any other way to achieve something like that?

3

3 Answers

27
votes

With bar(), you can directly use hatches (with some backends): http://matplotlib.org/examples/pylab_examples/hatch_demo.html: bar plot with hatches

It works by adding the hatch argument to your call to bar().


As for pie(), it does not have a hatch keyword. You can instead get the individual pie chart patches and add hatches to them: you get the patches with:

patches = pie(…)[0]  # The first element of the returned tuple are the pie slices

then you apply the hatches to each slice (patch):

patches[0].set_hatch('/')  # Pie slice #0 hatched.

(hatches list at https://matplotlib.org/api/_as_gen/matplotlib.patches.Patch.html#matplotlib.patches.Patch.set_hatch).

And you apply the changes with:

pyplot.draw()

Hatched pie chart]

38
votes
import matplotlib.pyplot as plt

fig = plt.figure()

patterns = [ "/" , "\\" , "|" , "-" , "+" , "x", "o", "O", ".", "*" ]

ax1 = fig.add_subplot(111)
for i in range(len(patterns)):
    ax1.bar(i, 3, color='red', edgecolor='black', hatch=patterns[i])


plt.show()

enter image description here

It's in the documentation here.

Okay - so to texture a piechart, you need to do this:

if you look here:

Return value:
If autopct is None, return the tuple (patches, texts):

patches is a sequence of matplotlib.patches.Wedge instances
texts is a list of the label matplotlib.text.Text instances.

so then we look at the Wedges page, and see that it has a set_hatch() method.

so we just need to add a few lines to the piechart demo and...

Example 1:

import matplotlib.pyplot as plt

fig = plt.figure()

patterns = [ "/" , "\\" , "|" , "-" , "+" , "x", "o", "O", ".", "*" ]

ax1 = fig.add_subplot(111)
for i in range(len(patterns)):
    ax1.bar(i, 3, color='red', edgecolor='black', hatch=patterns[i])


plt.show()

Example 2:

"""
Make a pie chart - see
http://matplotlib.sf.net/matplotlib.pylab.html#-pie for the docstring.

This example shows a basic pie chart with labels optional features,
like autolabeling the percentage, offsetting a slice with "explode",
adding a shadow, and changing the starting angle.

"""

from pylab import *
import math
import numpy as np

patterns = [ "/" , "\\" , "|" , "-" , "+" , "x", "o", "O", ".", "*" ]


def little_pie(breakdown,location,size):
    breakdown = [0] + list(np.cumsum(breakdown)* 1.0 / sum(breakdown))
    for i in xrange(len(breakdown)-1):
        x = [0] + np.cos(np.linspace(2 * math.pi * breakdown[i], 2 * math.pi *    
                          breakdown[i+1], 20)).tolist()
        y = [0] + np.sin(np.linspace(2 * math.pi * breakdown[i], 2 * math.pi * 
                          breakdown[i+1], 20)).tolist()
        xy = zip(x,y)
        scatter( location[0], location[1], marker=(xy,0), s=size, facecolor=
               ['gold','yellow', 'orange', 'red','purple','indigo','violet'][i%7])

figure(1, figsize=(6,6))

little_pie([10,3,7],(1,1),600)
little_pie([10,27,4,8,4,5,6,17,33],(-1,1),800)

fracs = [10, 8, 7, 10]
explode=(0, 0, 0.1, 0)

piechart = pie(fracs, explode=explode, autopct='%1.1f%%')
for i in range(len(piechart[0])):
    piechart[0][i].set_hatch(patterns[(i)%len(patterns)])


show()

enter image description here

0
votes

This may help you:

http://matplotlib.org/examples/pylab_examples/demo_ribbon_box.html

which uses matplotlib.image.BboxImage

I believe this can resize a given image according to input data.