Erstellen eines interaktiven Histogramms mit Matplotlib

PythonPythonBeginner
Jetzt üben

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

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab werden wir lernen, wie man mithilfe von Matplotlib ein interaktives Histogramm erstellt. Die Interaktivität wird in ECMAScript (JavaScript) codiert und in einem Nachbearbeitungsschritt in den SVG-Code eingefügt. Das resultierende Histogramm wird Balken haben, die durch Klicken auf Legendenmarker ausgeblendet oder angezeigt werden können.

Tipps für die virtuelle Maschine

Nachdem der Start der virtuellen Maschine abgeschlossen ist, klicken Sie in der linken oberen Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu nutzen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund von Einschränkungen in Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback ab, und wir werden das Problem für Sie prompt beheben.

Histogramm, Legende und Titel erstellen

Zunächst werden wir das Histogramm, die Legende und den Titel mit Matplotlib erstellen. Wir werden auch jedem Objekt mithilfe der Methode set_gid() IDs zuweisen. Dies wird helfen, die in Python erstellten Matplotlib-Objekte mit den entsprechenden SVG-Konstrukten zu verknüpfen, die im zweiten Schritt analysiert werden.

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 = ['Kaninchen', 'Frösche']
H = plt.hist([r, r1], label=labels)
containers = H[-1]
leg = plt.legend(frameon=False)
plt.title("Von einem Webbrowser her können Sie auf den Legendenmarker klicken,\n"
          "um das entsprechende Histogramm an- oder auszublenden.")

## 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}')

Interaktivität zum Histogramm hinzufügen

Als nächstes werden wir der Histogramm-Interaktivität hinzufügen, indem wir den SVG-Code mit ECMAScript (JavaScript) modifizieren. Wir werden den Attributen der Patch- und Textobjekte mithilfe der set()-Methode Attribute hinzufügen. Wir werden auch eine globale Variable container erstellen, die die IDs der Patches speichert, die zu jedem Histogramm gehören. Schließlich werden wir eine Funktion toggle_hist() erstellen, die das Sichtbarkeitsattribut aller Patches jedes Histogramms und die Transparenz des Markers selbst setzt.

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")

Betrachten des interaktiven Histogramms

Schließlich können wir das interaktive Histogramm betrachten, indem wir die SVG-Datei in einem Webbrowser öffnen. Um die Balken auszublenden oder anzuzeigen, klicken Sie einfach auf die Legendenmarker.

Zusammenfassung

In diesem Lab haben wir gelernt, wie man mithilfe von Matplotlib ein interaktives Histogramm erstellt. Wir haben ECMAScript (JavaScript) verwendet, um der Histogramm-Interaktivität hinzuzufügen, indem wir den SVG-Code modifiziert haben. Das resultierende Histogramm hat Balken, die durch Klicken auf Legendenmarker ausgeblendet oder angezeigt werden können.