Demo-PY1: Python Tutorial
Jupyter Widgets erstellen
Im ersten und zweiten Teil von Demo-PY1 wurden die Grundlagen der Programmiersprache Python und die Verwendung von Jupyter Notebook als webbasierte Entwicklungs- und Laufzeitumgebung vermittelt. Der dritte Teil der Tutorial Reihe konzentriert sich auf die Verwendung von Widgets in einem Jupyter Notebook.
Was sind also Jupyter Widgets? Jupyter Widgets sind Steuerelemente, die über die Python-Bibliothek ipywidgets zur Verfügung gestellt werden, und mit deren Hilfe man ein Jupyter Notebook um grafische Benutzeroberflächen erweitern kann.
Wie bei der Erstellung graphischer Benutzeroberflächen üblich, müssen zunächst die passenden Steuerelemente ausgewählt, und dann die Steuerelemente durch Eventhandler mit Daten verknüpft werden. Die ipywidgets -Bibliothek bietet folgende Widget-Kategorien:
- Numerische Widgets: IntSlider, FloatSlider, IntRangeSlider, ...
- String-Widgets: Text, Textarea, Combobox, HTML, HTML Math
- Auswahl-Widgets: Dropdown, RadioButton, Select, ...
- Button, Image, Datum-Picker, File Upload, Output...
- Container- und Layout-Widgets: Box, HBox, VBox, Accordion und Tab,...
Widgets können entweder explizit als Steuerelemente mit Eventhandling erstellt werden, oder implizit via der interact()- oder interactive_output()-Funktionalität.
Motivation
Warum Widgets?
Jupyter Notebook-Skripte sind durch die Aufteilung in Codezellen schon interaktiv und flexibel. Mit Hilfe von Widgets können die Skripte um grafische Benutzeroberflächen erweitert und damit noch benutzerfreundlicher gestaltet werden. Dies ist z.B. dann interessant, wenn Jupyter Notebooks Anwendern zur Verfügung gestellt werden, die sich mit Python-Programmierung und der Einstellung von Konfigurationsparametern weniger auskennen.
interact()
Mit Hilfe der interact-Methode können Widgets automatisch erstellt
und mit den Parametern benutzerdefinierter Funktionen verknüpft werden.
Eine typische Anwendung ist die interaktive Visualisierung von Daten aus einem größeren Datensatz.
Der Vorteil besteht darin, dass die Steuerelemente automatisch generiert werden, ohne dass man sie
explizit erstellen und Eventhandler schreiben muss.
interactive_output()
Die Funktion interactive_output
ermöglicht wie die Funktion interact das Verknüpfen
von GUI-Elementen mit Daten, gibt jedoch mehr Kontrolle über den Ablauf, da
bei Funktionsaufruf die interaktive Visualisierung zwar erstellt, jedoch noch nicht ausgegeben wird.
Die Darstellung erfolgt erst durch expliziten Aufruf der display-Funktion, dadurch
kann man größere und komplexere Benutzeroberflächen erstellen.
Übersicht
Das Tutorial ist in zehn Abschnitte gegliedert:
Das Tutorial ist als Google Colab Notebook online verfügbar:
1 Vorbereitung
Als Vorbereitung sollte zunächst die Anaconda-Plattform heruntergeladen und installiert werden. Dabei werden Python und Jupyter Notebook
gleich mit installiert. Die Details der Anaconda-Installation sind in Vorbereitung: Installation von Python und Anaconda
erläutert.
Danach wird ein neues Jupyter Notebook mit dem Namen JUNO2 erstellt, wie im Abschnitt Jupyter Notebooks verwenden
beschrieben.
2 Bibliotheken importieren
Wir verwenden die ipywidgets-Bibliothek, um in ein Jupyter Notebook interaktive Steuerelemente einzufügen, und die interact-Funktion, um Steuerelemente mit den Parametern benutzerdefinierter Funktionen zu verknüpfen.
from IPython.display import display
import ipywidgets as widgets
from ipywidgets import interact, Layout
3 Steuerelemente erstellen
Die ipywidgets-Bibliothek stellt verschiedene Steuerelemente zur Verfügung (Text-Eingabefelder, Auswahlfelder, Buttons, Datum-Picker ...). Häufig benötigte Widgets sind das Text-Widget, das IntSlider-Widget und das Dropdown-Widget. Um ein Widget zu erstellen, kann wie im Code unten der Name angegeben werden (hier: IntSlider), gefolgt von einer Reihe von Attributen (z.B. value, description, disabled), die die Werte und das Aussehen des Widgets festlegen.
from ipywidgets import IntSlider
IntSlider(value=7,min=0,max=10,step=1,
description='IntSlider:',orientation='horizontal')
Besser ist jedoch, das Widget zunächst unter einem Namen zu speichern und erst in einem zweiten Schritt mit display() auszugeben, wie im folgenden Beispiel.
Beispiel: Drei Widgets erstellen und anzeigen
from ipywidgets import Text, IntSlider, Dropdown
# Erstelle ein neues Text-Eingabefeld tb1 und zeige es an.
tb1 = Text(value='Text eingeben',
description='Text-Widget: ')
display(tb1)
# Erstelle IntSlider-Widget is1 und zeige es an.
is1 = IntSlider(value=7, min=0, max=10,
step=1, description='IntSlider: ')
display(is1)
# Erstelle Dropdown-Widget dd1 und zeige es an
dd1 = Dropdown(options=['1', '2', '3'],
value='2', description='Dropdown: ')
display(dd1)
Die erstellten Widgets sehen ähnlich aus wie abgebildet. Über die Attribute der Widgets können ihre Wertebereiche und Defaultwerte im Detail konfiguriert werden.
Widgets werden verwendet, um Benutzereingaben abzufragen oder Daten darzustellen.
Der Wert eines Widgets wird mit dem value-Attribut ausgelesen.
D.h. um zu wissen, welche Auswahl ein
Anwender mit dem Dropdown-Widget getroffen hat, fragen wir das value-Attribut des Widgets ab.
Da einige Widgets wie z.B. der IntSlider einen numerischen Wert haben, konvertieren wir den Wert für die Ausgabe mit str() in einen String,
damit in der print-Anweisung kein Fehler passiert.
print('Wert des Widgets is1 ist: ' + str(is1.value))
print('Wert des Widgets dd1 ist: ' + str(dd1.value))
Ausgabe
print('Wert des Widgets tb1 ist: ' + str(tb1.value));
print('Wert des Widgets is1 ist: ' + str(is1.value));
4 Eventhandler erstellen
Nach der Erstellung des Widgets werden für Aktionen wie z.B. Anklicken eines Buttons passende Eventhandler festgelegt.
Beispiel: Summe berechnen
Um die Summe zweier Zahlen zu berechnen, erstellen wir drei Text-Widgets und ein Button-Widget. Dies einfache Beispiel zeigt,
wie mit Hilfe eines Eventhandlers die Werte zwischen verschiedenen Widgets übergeben werden.
- Für das Button-Widget wird eine Eventhandler-Funktion on_button_clicked() definiert.
- In der Funktion lesen wir die Eingaben aus textbox1 und textbox2 aus, addieren sie, und weisen das Ergebnis dem Wert von textbox3 zu.
import ipywidgets
from ipywidgets import Text, Button
# Erstelle zwei Text-Eingabefelder
textbox1 = Text(description='a'); display(textbox1)
textbox2 = Text(description='b');display(textbox2)
# ... einen Button
button = Button(description='Berechnen!',
layout=Layout(width='200px'))
button.style.button_color = 'lightgreen'
display(button)
# ... und ein Text-Ausgabefeld für die Summe
textbox3 = Text(description='Summe')
display(textbox3)
# Definiere Eventhandler für den Button
def on_button_clicked(sender):
a = int(textbox1.value)
b = int(textbox2.value)
textbox3.value = str(a+b)
# ... und weise ihn dem on_click-Ereignis zu
button.on_click(on_button_clicked)
Die erstellten Widgets sehen ähnlich aus wie abgebildet. Wenn man im Text-Eingabefeld "a" 10 eingibt, im Text-Eingabefeld "20" und dann den Button anklickt, erscheint das Ergebnis in der Textbox "Summe".
5 Interact-Funktionalität
Mit Hilfe der interact-Methode können Widgets automatisch erstellt und mit den Parametern benutzerdefinierter Funktionen verknüpft werden. Dies ist nützlich, wenn man z.B. Parameter eines Plots über einen Slider einstellen möchte.
Der Typ des erstellten Widgets hängt vom Parameter der benutzerdefinierten Funktion ab.
Beispiel 1
Der interact-Aufruf im Code unten mit den Parametern myfunc1 und x = [1,2,3] erzeugt ein Dropdown-Widget mit den Elementen 1, 2, 3,
da das Argument x diese drei diskreten Werte annehmen kann.
# myfunc1 gibt einen Text aus, der von x abhängt
def myfunc1(x):
print('Auswahl: ' + str(x))
# interact erzeugt Dropdown-Widget
interact(myfunc1, x = [1, 2, 3]);
Das mit interact erstellte Widget sieht aus wie abgebildet: wenn der Anwender die Auswahl "2" trifft, wird die Funktion myfunc1 mit dem Parameter x = 2 aufgerufen und somit der Text "Auswahl: 2" ausgegeben.
Beispiel 2
Der interact-Aufruf im Code unten mit den Parametern myfunc2 und x = 'Text eingeben' erzeugt ein Text-Widget mit einem Default-Text,
der durch eine beliebige Texteingabe ersetzt werden kann.
# myfunc2 gibt den eingegebenen Text aus
def myfunc2(x):
print('Ihre Eingabe: ' + str(x))
interact(myfunc2, x = 'Text eingeben');
Das mit interact erstellte Widget sieht aus wie abgebildet: wenn der Anwender den Text "Hallo zusammen" eingibt, wird die Funktion myfunc2 mit dem Parameter x = 'Hallo zusammen' aufgerufen und somit der Text "Ihre Eingabe: Hallo zusammen" ausgegeben.
6 Interaktive Visualisierung einer Funktion
Wir zeichnen die Sinusfunktion über den Wertebereich [0, xmax] und stellen die obere Grenze xmax des Wertebereichs über einen mit interact() erzeugten Slider ein.
import matplotlib.pyplot as plt
from numpy import arange,sin,pi
# Definiere myplot-Funktion
def myplot(xmax):
x = arange(0, xmax, 0.01);y = sin(2*pi*x);
plt.plot(x,y);
# Erstelle ein Widget für den Plot mit Hilfe von interact
interact(myplot, xmax = (pi/2,4*pi));
Erläuterung des Codes:
- Zeile 1-2: Importiere die matplotlib-Bibliothek und aus Numpy die Funktionen arange und sin und die Konstante pi
- Zeile 3-6: Definiere die Funktion myplot(), die die Sinus-Funktion über den Wertebereich [0, xmax] darstellt.
- Zeile 5: Erstelle eine Diskretisierung des Intervalls [0, xmax] mit Schrittweite 0.01 mit Hilfe der numpy-Funktion arange.
- Zeile 8: Verknüpfe die Funktion myplot mit dem Argument xmax, dem wir den Wertebereich (pi/2,4*pi) zuweisen. Da der Parameter xmax einen Wertebereich darstellt, wird hier ein FloatSlider erstellt.
Das Floatslider-Widget, das durch diesen Code erstellt wird, sieht initial aus wie abgebildet: der FloatSlider wird mit dem mittleren Wert des Intervalls initialisiert. Durch Ziehen des Sliders wird der Wertebereich der Funktion auf den eingestellten Wert von xmax angepasst.
7 Interaktive Visualisierung eines Datensatzes
Eine zweite nützliche Anwendung der interact-Funktion ist bei der Visualisierung von Datensätzen, die aus CSV-Dateien
in einen Pandas DataFrame eingelesen werden.
Ehe man die Daten für eine weitere Datenanalyse vorbereitet, ist es oft hilfreich, einzelne Spalten grafisch darzustellen,
um die Struktur der Daten besser zu verstehen.
Im ersten Schritt lesen wir einen Datensatz mit Stromverbrauchsdaten aus einer CSV-Datei in einen Pandas DataFrame ein,
und zeigen die ersten fünf Zeilen zur Kontrolle an.
import pandas as pd
# Lese CSV-Datei ein mit der Pandas-Funktion read_csv ein
df = pd.read_csv('daten.csv', index_col=0, parse_dates=True)
# Zeige erste drei DataFrames zur Kontrolle an
df.head(5)
Im zweiten Schritt definieren wir eine Funktion select_data(), die eine über den Parameter "spalten" ausgewählte Spalte grafisch darstellt. Durch einen interact-Aufruf wird diese benutzerdefinierte Funktion mit der Liste "spalten" verknüpft, die die Spaltennamen der Tabelle enthält, und so ein Dropdown für die Auswahl der Spalten generiert.
def select_data(spalten): # spalten enthält die ausgewählte Spalte
df2 = df.loc[:,spalten]; # Wähle Spalten aus
ax = df2.plot();
ax.set_ylabel('Tägl. Verbrauch (GWh)');
interact(select_data, spalten=['Verbrauch', 'Wind', 'Solar']);
8 Interactive Output
Eine fortgeschrittenere Art der Visualisierung kann mit Hilfe der Funktion interactive_output erreicht werden. Der Unterschied zur interact-Funktion besteht darin, dass die Widgets der Benutzeroberfläche explizit erstellt und dann durch die Funktion interactive_output mit den Dateninhalten verknüpft werden, dadurch hat man mehr Kontrolle über die Gestaltung der Widgets. In dem folgenden Beispiel wird die interaktive Visualisierung einer Sinusfunktion über einen einstellbaren Wertebereich mit interactive_output umgesetzt.
- Zeile 1-4: Hier definieren wir zunächst die Funktion myplot, die eine Sinus-Funktion über den Wertebereich [0, xmax] darstellt.
- Zeile 5: Hier erstellen wir ein Widget ui_max vom Typ FloatSlider mit Beschriftung xmax und Wertebereich [π/2, 2*π].
- Zeile 6: Die Funktion interactive_output erhält als Argumente die Funktion myplot, sowie für die Einstellung des Wertebereichs das Slider-Widget ui_max, und liefert eine Ausgabe "out" vom Typ widget.Output zurück.
- Zeile 7: Das Slider-Widget und die Ausgabe der Funktion myplot werden in ein Container-Widget gepackt, hier: in eine VBox, deren Layout noch durch weitere Angaben festgelegt wird.
def myplot(xmax):
x = arange(0, xmax, 0.01)
y = sin(2*pi*x)
plt.plot(x,y)
ui_xmax = FloatSlider(description='xmax', value=10, min=pi/2, max=2*pi);
out = interactive_output(myplot, {'xmax': ui_xmax});
display(VBox([ui_xmax,out], layout=Layout(width='50%',border='1px dotted blue')))
9 Container-Widgets
Für die Gestaltung einer ansprechenden und übersichtlichen Benutzeroberfläche stehen eine Reihe von Container-Widgets zur Verfügung, mit deren Hilfe die anderen Steuerelemente gruppiert und angeordnet werden können: Box, HBox, VBox, Accordion, Tab etc. Die Box-Widgets sind Container, die andere Kinder-Widgets enthalten und deren Layout (Größe, Rahmen, Farbe) angepasst werden kann. Die Kinder-Widgets eine HBox sind horizontal, die Kinder-Widgets einer VBox sind vertikal angeordnet. Das Tab-Widget wird zur Erstellung von Registerkarten verwendet, das Accordion-Widget zur Erstellung einklappbarer Boxen.
Beispiel: Container-Widgets
Das nächste Beispiel zeigt die Erstellung einer Benutzeroberfläche, die die Widgets-Container Tab und VBox verwendet, um einen Stromverbrauchsdatensatz aus einer csv-Datei einzulesen und in einer ersten Registerkarte formatiert anzuzeigen. In einer zweiten Registerkarte wird eine interaktive grafische Visualisierung der Daten eingebaut, wie im Video angezeigt.
Video: Container-Widgets
Schritt 1 : Hilfsfunktionen definieren
Zunächst werden die Hilfsfunktionen display_dataframe (für die formatierte Darstellung eines Pandas-Dataframes)
und select_data (für das Plotten ausgewählter Spalten des DataFrames) definiert.
Mit Hilfe der ersten Funktion können wir die Ausgabe des DataFrames auf eine festgelegte Anzahl Zeilen und Spalten
beschränken, z.B. werden mit display_dataframe(df, 10, 2) die ersten und letzten 5 Zeilen und die ersten 2 Spalten des
Datensatzes ausgegeben. Die zweite Funktion select_data hat als Eingabeparameter eine Liste von Spalten, wählt
diese Spalten aus dem DataFrame df aus und stellt sie grafisch dar. Das DataFrame df wird hier als globale Variable angenommen,
muss also vor der Verwendung der Funktion definiert werden, wie es im zweiten Schritt passiert.
Wichtig: die benötigten Programmpakete, z.B. Pandas oder ipywidgets, müssen stets als Erstes importiert werden.
import pandas as pd
import ipywidgets as widgets
def display_dataframe(df, rows=6, cols=6):
with pd.option_context('display.max_rows', rows,
'display.max_columns', cols):
display(df)
def select_data(spalten):
df2 = df.loc[:,spalten];
ax = df2.plot();
ax.set_ylabel('Tägl. Verbrauch (GWh)');
Schritt 2: Grafische Benutzeroberfläche
Für die Erstellung der GUI wird das Output-Widget benötigt, das Jupyter Notebook-Ausgaben speichern und ausgeben kann.
Weiterhin wird das with-Schlüsselwort verwendet, um Code-Blöcke den korrekten Reiter-Ausgaben zuzuordnen und
dabei eine implizite Fehlerbehandlung zu ermöglichen.
- Zeile 1-2: Importieren der benötigte Klassen und Funktionen
- Zeile 5-8: Einlesen der Daten aus der csv-Datei und Ausgabe mit Hilfe der Funktion display_dataframe
- Zeile 10-12: Erzeugen eines Dropdown-Widgets für die Spalten-Auswahl. Die möglichen Optionen werden aus den Spalten des Dataframes bezogen: ["Verbrauch", "Wind", "Solar", "Wind+Solar"].
- Zeile 13: Erzeugen einer interaktiven Ausgabe-Grafik mit Hilfe der Funktion interactive_output
- Zeile 15-19: Erstellen des Tab-Widgets mit zwei Registerkarten, Festlegen der Titel und Ausgabe des Tabs.
from ipywidgets import Output, Layout, Dropdown, Tab, VBox
from ipywidgets import interactive_output
out1, out2 = Output(), Output()
with out1:
file = 'https://elab2go.de/demo-py5/opsd_2018.csv'
df = pd.read_csv(file, header=0, sep = ",",
index_col=0, parse_dates=True)
display_dataframe(df)
with out2:
ui_spalten = Dropdown(description='Auswahl:',
options=df.columns[0:], value='Verbrauch',
layout=Layout(width='auto'))
out = interactive_output(select_data, {'spalten': ui_spalten});
display(VBox([ui_spalten, out]))
tab = Tab(children = [out1, out2],
layout=Layout(width='70%'))
tab.set_title(0, 'Daten')
tab.set_title(1, 'Grafik')
display(tab)
YouTube-Video
Die Verwendung des Jupyter Notebook JUNO2.ipynb wird durch ein 7-Minuten-Video (Screencast mit zusätzlichen Erläuterungen) veranschaulicht.
Video: Jupyter Widgets verwenden
Video: Erste Schritte mit Jupyter Notebook
Autoren, Tools und Quellen
Autoren:
Prof. Dr. Eva Maria Kiss
M.Sc. Anke Welz
Tools:
elab2go-Links:
- [1] Python-Tutorial: elab2go/demo-py1
- [2] Jupyter Notebook Tutorial: elab2go/demo-py1/jupyter-notebooks.php
- [3] Datenverwaltung und -Visualisierung mit Pandas: elab2go.de/demo-py2
- [4] Clusteranalyse mit scikit-learn: elab2go.de/demo-py3
- [5] Predictive Maintenance mit scikit-learn: elab2go.de/demo-py4
- [6] Machine Learning-Modellierung mit Keras und Tensorflow: elab2go.de/demo-py5
Quellen und weiterführende Links:
- [1] Project Jupyter Webseite: jupyter.org/
- [2] Jupyter Widgets Webseite: ipywidgets.readthedocs.io/
- [3] Markdown Syntax: daringfireball.net/projects/markdown/syntax
- [4] Offizielle Python Dokumentation bei python.org: docs.python.org/3/tutorial/
sehr umfangreich, Nachschlagewerk, hier findet man Dokumentationen für spezifische Python-Versionen - [5] Python Tutorial bei Google Developers: developers.google.com/edu/python/introduction
umfangreich, für Fortgeschrittene, verweist auf die offizielle Dokumentation