8

I have three algorithms, A, B, and C. I've run them on different datasets and would like to graph their runtimes on each as a grouped boxplot in Python.

As a visual example of what I want, I made a terrible drawing, but hopefully it gets the point across.

boxplot graph drawing

If my data in python looks like this:

import numpy as np
import random

data = {}
data['dataset1'] = {}
data['dataset2'] = {}
data['dataset3'] = {}

n = 5
for k,v in data.iteritems():
    upper = random.randint(0, 1000)
    v['A'] = np.random.uniform(0, upper, size=n)
    v['B'] = np.random.uniform(0, upper, size=n)
    v['C'] = np.random.uniform(0, upper, size=n)

How can I make my plot look like the picture I drew?

lollercoaster
  • 15,969
  • 35
  • 115
  • 173
  • 1
    If you use boxplots regularly, take a look at https://github.com/matplotlib/matplotlib/pull/2643 which is adding a more flexible interface. – tacaswell Dec 04 '13 at 03:32
  • Possible duplicate of [matplotlib: Group boxplots](http://stackoverflow.com/questions/16592222/matplotlib-group-boxplots) – bluenote10 Jan 12 '16 at 13:36

1 Answers1

18

It's easiest to do this with independent subplots:

import matplotlib.pyplot as plt
import numpy as np
import random

data = {}
data['dataset1'] = {}
data['dataset2'] = {}
data['dataset3'] = {}

n = 500
for k,v in data.iteritems():
    upper = random.randint(0, 1000)
    v['A'] = np.random.uniform(0, upper, size=n)
    v['B'] = np.random.uniform(0, upper, size=n)
    v['C'] = np.random.uniform(0, upper, size=n)

fig, axes = plt.subplots(ncols=3, sharey=True)
fig.subplots_adjust(wspace=0)

for ax, name in zip(axes, ['dataset1', 'dataset2', 'dataset3']):
    ax.boxplot([data[name][item] for item in ['A', 'B', 'C']])
    ax.set(xticklabels=['A', 'B', 'C'], xlabel=name)
    ax.margins(0.05) # Optional

plt.show()

enter image description here

Joe Kington
  • 275,208
  • 71
  • 604
  • 463
  • perfectly what I wanted! thanks. always amazed how versatile matplotlib in python is. – lollercoaster Dec 04 '13 at 01:39
  • 1
    @lollercoaster - Happy to help! Your sketch and example data made your question very clear and easy to answer, for whatever it's worth. Excellent question! – Joe Kington Dec 04 '13 at 01:46
  • @JoeKington How did you get rid of the `yticklabels` on plots 2 and 3? They appear on all three plots for me, and if I remove them from one they disappear from all three because the `yaxis` is shared. – Deditos Feb 06 '14 at 12:57
  • @Deditos - Using `subplots` with `sharey=True` should automatically hide them, but if it's not for some reason, use `plt.setp(ax2.get_yticklabels(), visible=False)` (and repeat for `ax3`). What you're running into is a bit of a classic gotcha with shared axes. The `plt.setp(..., visible=False)` is a workaround so that they're still shown on the first axes, but not on the other shared ones. – Joe Kington Feb 06 '14 at 14:37
  • 1
    @JoeKington: It's probably because I'm using an old matplotlib version, but that manual `setp` command does the trick, thanks! – Deditos Feb 06 '14 at 17:30