3

I'm trying to make a plot using matplotlib that resembles the following:

Desired sort of image

However, I'm not quite sure which type of graph to use. My data has the following form, where start x position is a positive value greater or equal to 0:

<item 1><start x position><end x position>
<item 2><start x position><end x position>

Looking at the docs, I see that there is barh and errorbar, but I'm not sure if its possible to use barh with a start offset. What would be the best method to use, given my type of data? I'm not that familiar with the library, so I was hoping to get some insight.

1
  • There is some sort of consensus on using the term "Range Bar Graph" for the type of disposition that you've asked for, and at the same time thare is no web reference to a matplotlib solution to this problem. May I ask you to change the title of your question to a more searchable one? E.g., stemming from your own, "Proper plot to use in matplotlib for a range bar graph?" or maybe the more direct "Drawing a range bar graph using Matplotlib"... Thank you for the consideration, Commented Apr 6, 2015 at 8:41

1 Answer 1

5

Appetizer

exactly what you asked for

Commented Code

As far as I know, the most direct way to do what you want requires that you directly draw your rectangles on the matplotlib canvas using the patches module of matplotlib

A simple implementation follows

import matplotlib.pyplot as plt
import matplotlib.patches as patches

def plot_rect(data, delta=0.4):
    """data is a dictionary, {"Label":(low,hi), ... }
    return a drawing that you can manipulate, show, save etc"""

    yspan = len(data)
    yplaces = [.5+i for i in range(yspan)]
    ylabels = sorted(data.keys())

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.set_yticks(yplaces)
    ax.set_yticklabels(ylabels)
    ax.set_ylim((0,yspan))

    # later we'll need the min and max in the union of intervals
    low, hi =  data[ylabels[0]]
    for pos, label in zip(yplaces,ylabels):
        start, end = data[label]
        ax.add_patch(patches.Rectangle((start,pos-delta/2.0),end-start,delta))
        if start<low : low=start
        if end>hi : hi=end

    # little small trick, draw an invisible line so that the x axis
    # limits are automatically adjusted...
    ax.plot((low,hi),(0,0))

    # now get the limits as automatically computed
    xmin, xmax = ax.get_xlim()
    # and use them to draw the hlines in your example
    ax.hlines(range(1,yspan),xmin,xmax)
    # the vlines are simply the x grid lines
    ax.grid(axis='x')
    # eventually return what we have done
    return ax

# this is the main script, note that we have imported pyplot as plt

# the data, inspired by your example, 
data = {'A':(1901,1921),
        'B':(1917,1935),
        'C':(1929,1948),
        'D':(1943,1963),
        'E':(1957,1983),
        'F':(1975,1991),
        'G':(1989,2007)}

# call the function and give its result a name
ax = plot_rect(data)
# so that we can further manipulate it using the `axes` methods, e.g.
ax.set_xlabel('Whatever')
# finally save or show what we have
plt.show()

The result of our sufferings has been shown in the first paragraph of this post...

Addendum

Let's say that you feel that blue is a very dull color...

The patches you've placed in your drawing are accessible as a property (aptly named patches...) of the drawing and modifiable too, e.g.,

ax = plot_rect(data)
ax.set_xlabel('Whatever')
for rect in ax.patches:
    rect.set(facecolor=(0.9,0.9,0.2,1.0), # a tuple, RGBA
          edgecolor=(0.6,0.2,0.3,1.0),
          linewidth=3.0)
plt.show()

NO. MORE. DULLNESS.

In my VH opinion, a custom plotting function should do the least indispensable to characterize the plot, as this kind of post-production is usually very easy in matplotlib.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.