Exemple intéressant d'histogramme horizontal avec matplotlib réalisé par Nicolas P. Rougier.
Code source:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (C) 2011 Nicolas P. Rougier
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of the glumpy Development Team nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# -----------------------------------------------------------------------------
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# ----------
# Data to be represented
diseases = ['Disease 1', 'Disease 2','Disease 3','Disease 4','Disease 5',
'Disease 6', 'Disease 7','Disease 8','Disease 9','Disease 10']
men_deaths = np.random.uniform(50000,100000,len(diseases))
men_cases = men_deaths+np.random.uniform(10000,50000,len(diseases))
women_deaths = np.random.uniform(50000,100000,len(diseases))
women_cases = women_deaths+np.random.uniform(10000,50000,len(diseases))
# ----------
# Choose some nice colors
matplotlib.rc('axes', facecolor = 'white')
matplotlib.rc('figure.subplot', wspace=.65)
matplotlib.rc('grid', color='white')
matplotlib.rc('grid', linewidth=1)
# Make figure background the same colors as axes
fig = plt.figure(figsize=(12,8), facecolor='white')
# --- MEN data ---
axes_left = plt.subplot(121)
# Keep only top and right spines
axes_left.spines['left'].set_color('none')
axes_left.spines['bottom'].set_color('none')
axes_left.xaxis.set_ticks_position('top')
axes_left.yaxis.set_ticks_position('right')
axes_left.spines['top'].set_position(('data',len(diseases)-.75))
axes_left.spines['top'].set_color('w')
# Set axes limits
plt.xlim(150000,0)
plt.ylim(0,len(diseases))
# Set ticks labels
plt.xticks([150000, 100000, 50000, 0],
['150000', '100000', '50000', 'MEN'])
axes_left.get_xticklabels()[-1].set_weight('bold')
axes_left.get_xticklines()[-1].set_markeredgewidth(0)
for label in axes_left.get_xticklabels():
label.set_fontsize(10)
plt.yticks([])
# Plot data
for i in range(len(men_deaths)):
# Death
value = men_cases[i]
p = patches.Rectangle(
(0, i+0.125), value, 0.75, fill=True, transform=axes_left.transData,
lw=0, facecolor='blue', alpha=0.1)
axes_left.add_patch(p)
# New cases
value = men_deaths[i]
p = patches.Rectangle(
(0, i+0.25), value, 0.5, fill=True, transform=axes_left.transData,
lw=0, facecolor='blue', alpha=0.5)
axes_left.add_patch(p)
# Add a grid
axes_left.grid()
# --- WOMEN data ---
axes_right = plt.subplot(122, sharey=axes_left)
# Keep only top and left spines
axes_right.spines['right'].set_color('none')
axes_right.spines['bottom'].set_color('none')
axes_right.xaxis.set_ticks_position('top')
axes_right.yaxis.set_ticks_position('left')
axes_right.spines['top'].set_position(('data',len(diseases)-.75))
axes_right.spines['top'].set_color('w')
# Set axes limits
plt.xlim(0,150000)
plt.ylim(0,len(diseases))
# Set ticks labels
plt.xticks([0, 50000, 100000, 150000],
['WOMEN', '50000', '100000', '150000'])
axes_right.get_xticklabels()[0].set_weight('bold')
for label in axes_right.get_xticklabels():
label.set_fontsize(10)
axes_right.get_xticklines()[1].set_markeredgewidth(0)
plt.yticks([])
# Plot data
for i in range(len(women_deaths)):
# Death
value = women_cases[i]
p = patches.Rectangle(
(0, i+0.125), value, 0.75, fill=True, transform=axes_right.transData,
lw=0, facecolor='red', alpha=0.1)
axes_right.add_patch(p)
# New cases
value = women_deaths[i]
p = patches.Rectangle(
(0, i+0.25), value, 0.5, fill=True, transform=axes_right.transData,
lw=0, facecolor='red', alpha=0.5)
axes_right.add_patch(p)
# Add a grid
axes_right.grid()
# Y axis labels
# We want them to be exactly in the middel of the two y spines
# and it requires some computations
for i in range(len(diseases)):
x1,y1 = axes_left.transData.transform_point( (0,i+.5))
x2,y2 = axes_right.transData.transform_point((0,i+.5))
x,y = fig.transFigure.inverted().transform_point( ((x1+x2)/2,y1) )
plt.text(x, y, diseases[i], transform=fig.transFigure,
horizontalalignment='center', verticalalignment='center')
# Devil hides in the details...
arrowprops = dict(arrowstyle="-", connectionstyle="angle,angleA=0,angleB=90,rad=0")
x = men_cases[0]
axes_left.annotate('NEW CASES', xy=(.9*x, .5), xycoords='data',
horizontalalignment='right', fontsize= 10,
xytext=(-40, -3), textcoords='offset points',
arrowprops=arrowprops)
x = men_deaths[0]
axes_left.annotate('DEATHS', xy=(.9*x, .5), xycoords='data',
horizontalalignment='right', fontsize= 10,
xytext=(-50, -50), textcoords='offset points',
arrowprops=arrowprops)
x = women_cases[0]
axes_right.annotate('NEW CASES', xy=(.9*x, .5), xycoords='data',
horizontalalignment='left', fontsize= 10,
xytext=(+40, -3), textcoords='offset points',
arrowprops=arrowprops)
x = women_deaths[0]
axes_right.annotate('DEATHS', xy=(.9*x, .5), xycoords='data',
horizontalalignment='left', fontsize= 10,
xytext=(+50, -50), textcoords='offset points',
arrowprops=arrowprops)
# Done
plt.savefig('diseases.png', facecolor='white')
plt.show()