In matplotlib, how to draw a bar graphs of multiple datasets to put smallest bars to front?
matplotlib, plot, python
Solution
I know this is an old question, but I came across it for my own purposes, and since it seemed like something I'd do over and over, I put together a wrapper for the hist function (which is what I'll be using; modification to bar should be trivial):
from matplotlib import pyplot as mpl
from numpy import argsort, linspace
def hist_sorted(*args, **kwargs):
all_ns = []
all_patches = []
labels = kwargs.pop('labels', None)
if not labels:
labels = ['data %d' % (i+1) for i in range(len(args))]
elif len(labels) != len(args):
raise ValueError('length of labels not equal to length of data')
bins = kwargs.pop('bins', linspace(min(min(a) for a in args),
max(max(a) for a in args),
num = 11))
for data, label in zip(args, labels):
ns, bins, patches = mpl.hist(data, bins=bins, label=label, **kwargs)
all_ns.append(ns)
all_patches.append(patches)
z_orders = -argsort(all_ns, axis=0)
for zrow, patchrow in zip(z_orders, all_patches):
assert len(zrow) == len(patchrow)
for z_val, patch in zip(zrow, patchrow):
patch.set_zorder(z_val)
return all_ns, bins, all_patches
This takes the datasets as anonymous arguments, and any labels as keyword arguments (for the legend), as well as any other keyword argument usable with hist.
Problem
I want to put multiple datasets on a bar graph and stop the smaller bars being obscured by the larger ones, and I don't want to offset them. For example, bar(0, 1.) bar(0, 2.) only shows the second bar of height of 2.0, the first bar is hidden. Is there a way to get matplotlib to draw the bars with the smallest on top? NB I don't want a stacked bar graph or to offset the bars in x-directions. I can order all the data, from all datasets, by bar height and plot each bar individually in this order, but I'd prefer to plot each bar individually instead plot each dataset in turn Does anyone know a way of doing this? Many thanks