›  Demo-PY1: Python-Tutorial
›   Jupyter Notebook Widgets erstellen

Im ersten Teil von Demo-PY1 Python-Tutorial wurden die Grundlagen der Programmiersprache Python und der Verwendung von Jupyter Notebook vermittelt und wir haben mehrere interaktive Jupyter Notebook-Skripte mit Markdown-Zellen und Codezellen erstellt. Als Nächstes sehen wir, wie man in ein Jupyter Notebook-Skript Widgets einbaut, entweder explizit als Steuerelemente mit Eventhandling, oder implizit als Steuerelemente, die durch die interact()-Funktionalität mit einer benutzerdefinierten Funktion generiert werden.

info-icon Motivation

Widgets sind Steuerelemente (engl. Controls), mit deren Hilfe man ein Jupyter Notebook um grafische Benutzeroberflächen erweitern kann. Sie werden abhängig von den dargestellten Objekten in verschiedene Kategorien gruppiert, insbesondere:

  • Numerische Widgets: IntSlider, FloatSlider, ...

  • String-Widgets: Text, Textarea, Combobox, HTML, HTML Math

  • Auswahl-Widgets: Dropdown, RadioButton, Select, ...

  • Button, Image, Datum-Picker, File Upload, Output...

  • Container- und Layout-Widgets

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.

... und 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.

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.

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 

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.

 widgets.IntSlider(value=7,min=0,max=10,step=1,description='IntSlider:',orientation='vertical')

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

 # Erstelle ein neues Text-Eingabefeld tb1 und zeige es an. 
 tb1 = widgets.Text(value='Text eingeben', description='Text-Widget: ');display(tb1); 
 # Erstelle IntSlider-Widget is1 und zeige es an. 
 is1 = widgets.IntSlider(value=7,min=0, max=10, step=1, description='IntSlider: ');display(is1); 
 # Erstelle Dropdown-Widget dd1 und zeige es an 
 dd1 = widgets.Dropdown(options=['A', 'B', 'C'], value='A', 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)); 

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.

 # 3.1 Erstelle zwei Text-Eingabefelder 
 textbox1 = widgets.Text(description='a');display(textbox1); 
 textbox2 = widgets.Text(description='b');display(textbox2); 
 # ... einen Button mit benutzerdefiniertem Layout 
 button = widgets.Button(description='Berechnen!', layout=Layout(width='200px')); 
 button.style.button_color = 'lightgreen';display(button); 
 # ... und ein Text-Ausgabefeld für die Summe 
 textbox3 = widgets.Text(description='Summe');display(textbox3); 
 # 3.2 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".


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.


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 der interact()-Funktion 
 interact(myplot, xmax = (pi/2,4*pi)); 

Erläuterung des Codes:

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.


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']); 

YouTube-Video

Die Verwendung des Jupyter Notebook JUNO2.ipynb wird durch ein 7-Minuten-Video (Screencast mit zusätzlichen Erläuterungen) veranschaulicht.

Autoren, Tools und Quellen

Mit Beiträgen von:
 Prof. Dr. Eva Maria Kiss
 M. Sc. Anke Welz
Tools: Python, Anaconda, Jupyter-Notebook