Création d'un histogramme interactif avec Matplotlib

PythonPythonBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, nous allons apprendre à créer un histogramme interactif à l'aide de Matplotlib. L'interactivité est encodée en ECMAScript (JavaScript) et insérée dans le code SVG dans une étape de post-traitement. L'histogramme résultant aura des barres qui peuvent être masquées ou affichées en cliquant sur les marqueurs de légende.

Conseils sur la machine virtuelle

Une fois le démarrage de la machine virtuelle terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Carnet d'adresses pour accéder au carnet Jupyter pour pratiquer.

Parfois, vous devrez peut-être attendre quelques secondes pour que le carnet Jupyter ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations du carnet Jupyter.

Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez votre feedback après la session, et nous résoudrons rapidement le problème pour vous.

Créer l'histogramme, la légende et le titre

Tout d'abord, nous allons créer l'histogramme, la légende et le titre à l'aide de Matplotlib. Nous allons également attribuer des ID à chaque objet en utilisant la méthode set_gid(). Cela aidera à relier les objets Matplotlib créés en Python et les constructions SVG correspondantes qui sont analysées dans la deuxième étape.

import matplotlib.pyplot as plt
import numpy as np

## Fixing random state for reproducibility
np.random.seed(19680801)

## Create histogram, legend, and title
plt.figure()
r = np.random.randn(100)
r1 = r + 1
labels = ['Rabbits', 'Frogs']
H = plt.hist([r, r1], label=labels)
containers = H[-1]
leg = plt.legend(frameon=False)
plt.title("From a web browser, click on the legend\n"
          "marker to toggle the corresponding histogram.")

## Assign IDs to the SVG objects we'll modify
hist_patches = {}
for ic, c in enumerate(containers):
    hist_patches[f'hist_{ic}'] = []
    for il, element in enumerate(c):
        element.set_gid(f'hist_{ic}_patch_{il}')
        hist_patches[f'hist_{ic}'].append(f'hist_{ic}_patch_{il}')

## Set IDs for the legend patches
for i, t in enumerate(leg.get_patches()):
    t.set_gid(f'leg_patch_{i}')

## Set IDs for the text patches
for i, t in enumerate(leg.get_texts()):
    t.set_gid(f'leg_text_{i}')

Ajouter de l'interactivité à l'histogramme

Ensuite, nous allons ajouter de l'interactivité à l'histogramme en modifiant le code SVG à l'aide d'ECMAScript (JavaScript). Nous allons ajouter des attributs aux objets patch et text en utilisant la méthode set(). Nous allons également créer une variable globale container qui stocke les ID des patches appartenant à chaque histogramme. Enfin, nous allons créer une fonction toggle_hist() qui définit l'attribut de visibilité de tous les patches de chaque histogramme et l'opacité du marqueur lui-même.

from io import BytesIO
import json
import xml.etree.ElementTree as ET

plt.rcParams['svg.fonttype'] = 'none'

## Save SVG in a fake file object
f = BytesIO()
plt.savefig(f, format="svg")

## Create XML tree from the SVG file
tree, xmlid = ET.XMLID(f.getvalue())

## Add attributes to the patch objects
for i, t in enumerate(leg.get_patches()):
    el = xmlid[f'leg_patch_{i}']
    el.set('cursor', 'pointer')
    el.set('onclick', "toggle_hist(this)")

## Add attributes to the text objects
for i, t in enumerate(leg.get_texts()):
    el = xmlid[f'leg_text_{i}']
    el.set('cursor', 'pointer')
    el.set('onclick', "toggle_hist(this)")

## Create script defining the function `toggle_hist`
script = """
<script type="text/ecmascript">
<![CDATA[
var container = %s

function toggle(oid, attribute, values) {
    /* Toggle the style attribute of an object between two values.

    Parameters
    ----------
    oid : str
      Object identifier.
    attribute : str
      Name of style attribute.
    values : [on state, off state]
      The two values that are switched between.
    */
    var obj = document.getElementById(oid);
    var a = obj.style[attribute];

    a = (a == values[0] || a == "")? values[1] : values[0];
    obj.style[attribute] = a;
    }

function toggle_hist(obj) {

    var num = obj.id.slice(-1);

    toggle('leg_patch_' + num, 'opacity', [1, 0.3]);
    toggle('leg_text_' + num, 'opacity', [1, 0.5]);

    var names = container['hist_'+num]

    for (var i=0; i < names.length; i++) {
        toggle(names[i], 'opacity', [1, 0])
    };
    }
]]>
</script>
""" % json.dumps(hist_patches)

## Add a transition effect
css = tree.find('.//{http://www.w3.org/2000/svg}style')
css.text = css.text + "g {-webkit-transition:opacity 0.4s ease-out;" + \
    "-moz-transition:opacity 0.4s ease-out;}"

## Insert the script and save to file
tree.insert(0, ET.XML(script))
ET.ElementTree(tree).write("svg_histogram.svg")

Consulter l'histogramme interactif

Enfin, nous pouvons consulter l'histogramme interactif en ouvrant le fichier SVG dans un navigateur web. Pour masquer ou afficher les barres, cliquez simplement sur les marqueurs de légende.

Résumé

Dans ce laboratoire, nous avons appris à créer un histogramme interactif à l'aide de Matplotlib. Nous avons utilisé ECMAScript (JavaScript) pour ajouter de l'interactivité à l'histogramme en modifiant le code SVG. L'histogramme résultant a des barres qui peuvent être masquées ou affichées en cliquant sur les marqueurs de légende.