In [15]:
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
Wir haben matplotlib bereits kennengelernt, als wir Graphen geplottet haben. Es handelt sich dabei um eine komplexe Grafikbibliothek, die es erlaubt, auch sehr komplexe Grafiken zu erstellen. Leider ist dies mnachmal mit einer gewissen Komplexität der Bibliothek selbst verbunden. Matplotlib kennt drei Modi:
In [2]:
import matplotlib.pyplot as plt
x = [10,20,30,40]
y = [5, 3, 7, 4]
plt.plot(x,y)
plt.show()
Anstelle von Python-Listen können wir auch numpy-Arrays oder pandas-Series verwenden:
In [14]:
import numpy as np
x = np.arange(10,60,10)
y = np.arange(1,6)
plt.plot(x,y)
plt.show()
Da die Menge der x-Werte der Anzahl der y-Werte entsprechen muss, ist es oft einfacher, die einen über eine Funktion aus den anderen zu erzeugen:
In [15]:
x = np.arange(0.0, 6.0, 0.01)
plt.plot(x, [x**2 for x in x])
plt.show()
Und auch hier gilt, dass wir mehrere Elemente, z.B. Linien, zeichnen können, bevor wir uns die Gesamtgrafik anzeigen lassen. (Das liegt übrigens daran, dass plt.hold() auf True voreingestellt ist; wenn man den Wert False setzt, dann wird nach jedem plot-Befehl der Canvas zurückgesetzt):
In [16]:
x = np.arange(0,6)
plt.plot(x, [0.75*xi for xi in x])
plt.plot(x, [2*xi for xi in x])
plt.plot(x, [3.2*xi for xi in x])
plt.show()
In [17]:
#oder das gleiche kürzer mit etwas Vektorenrechnung:
x = np.arange(0,6)
plt.plot(x, 0.75*x, x, 2*x, x, 3.2*x)
plt.show()
Das folgende Beispiel zeigt, wie wir 1) ein Netz im Hintergrund einsetzen, 2) Beschriftungen für die x- und y-Achse einfügen, 3) die x-Achse und y-Achse, die bislang automatisch gesetzt wurden, nun explizit setzen - und damit auch die Skalierung der Grafik, 4) den Titel der Grafik setzen, 5) .
In [18]:
#hier sind die schon bekannten Werte
x = np.arange(0,6)
#und hier zeichnen wir damit Linien
#Werte für color: b blue, c cyan, g green, k black, m magenta, r red, w white, y yellow,
#die Werte für label werden dann in der Legende verwendet
plt.plot(x, 0.75*x, color="b", label="zu langsam" )
plt.plot(x, 2*x, color="y", label="normal")
plt.plot(x, 3.2*x, color="r", label="zu schnell")
#Beschriftung der x-Achse
plt.xlabel("hier stehen die x-Werte")
#Beschriftung der y-Achse
plt.ylabel("hier stehen die y-Werte")
#mit dem folgenden Befehl setzen wir die Grenzen der x und y - Achsen
#die ersten beiden Zahlen bestimmen Anfang und Ende der x-Achse usw.
#automatisch würden hier die Werte [0,5,0,16] stehen
plt.axis([0,6,-1,18])
#zeichnet ein Netz hinter den Linien, womit sich oft Werte besser lesen lassen
plt.grid(True)
#hiermit setzen wir den Titel der Grafik
#title bestimmt den Titel für die Einzelgrafik und suptitle bestimmt den Titel für die Gesamtgrafik
#(man kann mehrere Grafiken in einer Gesamtgrafik zusammenfassen.)
plt.suptitle("Dies ist eine Beispielgrafik", fontsize=16, color="blue")
#erstellt eine Legende aus den labels der plot-Anweisungen und positioniert sie.
#andere Werte für loc sind 'upper/lower/center right/left'
plt.legend(loc="upper left")
#zeigt die Grafik an
plt.show()
Im folgenden Beispiel spezifizieren wir die Art der Linie, den Marker, die Linienbreite, aber auch den Ort und das Label der x- und y-Achsen sowie frei positionierbare Texte.
In [19]:
#hier sind die schon bekannten Werte
x = np.arange(0,6)
#und hier zeichnen wir damit Linien
#linestyle: - durchgezogene Linie, -- gestrichelte Linie, : gepunktete Linie
#marker (Auswahl): o ^s 1 2 < > p * h H + x D d
plt.plot(x, 0.75*x, color="b", marker="o", linestyle="-", linewidth=3, label="zu langsam" )
plt.plot(x, 2*x, color="y", marker="^", linestyle="--", linewidth=2, label="normal")
plt.plot(x, 3.2*x, color="r", marker="s", linestyle=":", linewidth=1, label="zu schnell")
#Beschriftung der x-Achse
plt.xlabel("hier stehen die x-Werte")
#Beschriftung der y-Achse
plt.ylabel("hier stehen die y-Werte")
#mit der Funktion xticks setzen wir die Position und das Label der Striche auf der X-Achse
#beides übergeben wir als Liste
plt.xticks(range(6), ["a","b","c","d","e","f"])
#ditto mit der y-Achse
plt.yticks(range(0,16,2), ["0k", "10k", "20k", "30k", "40k", "50k", "60k", "70k", "80k"])
#freier Text, der über die x,y Koordinaten positioniert wird
#mit plt.text() verwendet man die Koordinaten mit den Datenwerten
#plt.text(1, 7, "Hier steht Text")
#mit plt.figtext() ist der 0-Punkt unten links (0,0) und der Gegenpunkt oben rechts (1,1)
plt.figtext(0.3,0.6, "Hallo Du, warum kein Tex?")
#zeichnet ein Netz hinter den Linien, womit sich oft Werte besser lesen lassen
plt.grid(True)
#hiermit setzen wir den Titel der Grafik
plt.title("Dies ist eine Beispielgrafik")
#erstellt eine Legende aus den labels der plot-Anweisungen und positioniert sie.
#andere Werte für loc sind 'upper/lower/center right/left'
plt.legend(loc="upper left")
#zeigt die Grafik an
plt.show()
Hier noch einmal die ganzen Möglichkeiten, eine Grafik zu gestalten</br>
Man kann eine Grafik auf zweierlei Weise speichern. Zum einen können wir sie aus dem Anzeigefenster speichern, zum anderen können wir sie, ohne sie anzeigen zu lassen, abspeichern, indem wir plt.savefig() vor plt.show() aufrufen.
Oder eben mittels plt.savefig() - nicht vergessen: Sie können diesen Befehl nur vor plt.show() verwenden, nicht dahinter, da plt.show() die Grafik zurücksetzt.
In [20]:
x = [3, 4, 8, 4, 5]
plt.plot(x)
plt.savefig("example.png", dpi=200)
plt.show()
Pie-Charts kennen wir alle aus der Zeitung, z.B. bei der Anzeige von Wahlergebnissen. Sie dienen der Anzeige von Verteilungen einer Gesamtheit (z.B. alle Wahlstimmen) über eine kleine Anzahl von Einheiten (z.B. alle Parteien).
In [21]:
#Daten + labels
election = [38.3, 26.8, 11.0, 9.3, 4.0, 3.8, 6.8 ]
labels = ["CDU/CSU","SPD","Die Grünen","Die Linke","FDP","AfD","Sonstige"]
#plotting
plt.pie(election,labels=labels)
plt.show()
Leider funktionieren die Voreinstellungen hier nicht befriedigend: der Kreis wird als Elipse dargestellt, deshalb muss man die Gesamtgrafik (figure) explizit auf ein Quadrat setzen (mehr dazu unten). Außerdem können wir die Farben explizit setzen:
In [22]:
election = [38.3, 26.8, 11.0, 9.3, 4.0, 3.8, 6.8 ]
labels = ["CDU/CSU","SPD","Die Grünen","Die Linke","FDP","AfD","Sonstige"]
plt.figure(figsize=(7,7))
plt.pie(election,labels=labels)
plt.show()
Mit dem keyword explode können wir die Grafik außerdem etwas dynamischer gestalten; die einzelnen Kuchenstücke werden nun herausgerückt. Wir übergeben dem keyword eine Liste, die soviele Werte enthält, wie wir Kuchenstücke haben. Die Größe des Wertes zeigt an, um wieviel das Stück herausgeschoben ist.
Außerdem können wir mit dem keyword autopct festlegen, wie die Werte angezeigt werden sollen. Hier wird die Formatierungssprache verwendet, die auch im Python-Handbuch in Abschnitt 4.7.2 printf-style formatting erläutert wird.
In [23]:
explode = [0,0,0.1,0.1,0.2,0.2,0.3]
plt.figure(figsize=(7,7))
plt.pie(election,labels=labels,explode=explode, autopct='%1.1f%%')
plt.show()
Bar Charts sind Säulendiagramme, mit denen man ebenfalls die Ausprägung von wenigen Ergebnissen anzeigen kann (man sieht nur nicht so gut, dass es insgesamt 100% sind, dafür sind die Größenunterschiede besser zu sehen). Wir übergeben die x und y Werte als Listen, wobei der erste Eintrag in beiden Listen die Angaben für die erste Säulen enthält:
In [24]:
x = [1,2,3,4,5]
y = [20,50,40,60,20]
plt.bar(x,y)
plt.show()
Wenn wir die Daten schon in Form zusammengehöriger Tupels vorliegen haben, dann rufen wir einfach den Befehl entsprechend oft auf:
In [25]:
data = [(1,20),(2,50),(3,40),(4,60),(5,20)]
[plt.bar(x[0],x[1]) for x in data]
plt.show()
Nun stellen wir unsere Wahlergebnisse noch einmal dar:
In [26]:
import matplotlib.pyplot as plt
import numpy as np
election = [38.3, 26.8, 11.0, 9.3, 4.5, 3.8, 6.8 ]
labels = ["CDU/CSU","SPD","Die Grünen","Die Linke","FDP","AfD","Sonstige"]
color = ["black","red","green","red","yellow","brown","grey"]
#die x-Werte sind hier einfache Zahlen, da wir eigentlich nur eine Reihe brauchen
#da die Labels relativ breit sind, machen wir auch die bars mit width etwas breiter (default=0.8)
plt.bar(range(len(election)), election, color=color, width=0.9)
#aber nun wollen wir unsere Beschriftung der x-Achse ändern: sie soll die Dateien
#da die Ticks immer unter der ersten Linie einer Säule anfangen, wir aber den Text in der Mitte stehen haben wollen,
#müssen wir die Position der Labels im ersten Parameter etwas nach rechts verschieben, indem wir 0.4 hinzu addieren (Vektoralgebra!)
plt.xticks(np.arange(len(labels))+0.4, labels)
plt.show()
Histogramme werden zumeist verwendet, um Häufigkeiten in Form von Säulen anzuzeigen. Die Säulen repräsentieren die Häufigkeit, mit der Datenpunkte in diese Kategorie (bins) fallen. Wohlgemerkt: Das Histogramm zeigt an, wie häufig (= x-Wert) ein Datenpunkt mit einer gewissen Ausprägung (=y-Wert) vorkommt. Nehmen wir an, wir würfeln 20-mal mit einem 6-seitigen Würfel und lassen uns dann die Werte anzeigen:
Das ist natürlich besonders sinnvoll, wenn man sehr viele Werte hat:
In [ ]:
import matplotlib.pyplot as plt
import numpy as np
#Datenerzeugung: erzeugt 1000 Zufallszahlen, deren Verteilung der Normalverteilung folgt
y = np.random.randn(1000)
#plotting. default für bins = 10
plt.hist(y, color='k')
plt.show()
Indem wir die Anzahl der bins hochsetzen, können wir die Normalverteilung deutlicher sehen:
In [28]:
plt.hist(y,25)
plt.show()
In [29]:
import random
#Datenerzeugung: wir simulieren das Würfeln 20mal
x = [random.randint(1, 6) for i in range(20)]
#plotting
#alternatives setzen der Grenzen der y-Achse
plt.ylim(0,8)
plt.xlim(0.9,6)
plt.hist(x, bins=6,width=0.7)
plt.show()
x
Out[29]:
In [30]:
#komplexes Beispiel aus der matplotlib-Dokumentation:
N = 5
menMeans = (20, 35, 30, 35, 27)
womenMeans = (25, 32, 34, 20, 25)
menStd = (2, 3, 4, 1, 2)
womenStd = (3, 5, 2, 3, 3)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars: can also be len(x) sequence
p1 = plt.bar(ind, menMeans, width, color='r', yerr=womenStd)
p2 = plt.bar(ind, womenMeans, width, color='y',
bottom=menMeans, yerr=menStd)
plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.xticks(ind+width/2., ('G1', 'G2', 'G3', 'G4', 'G5') )
plt.yticks(np.arange(0,81,10))
plt.legend( (p1[0], p2[0]), ('Men', 'Women') )
plt.show()
Scatter plots visualisieren Datenwerte in Abhängigkeit von zwei Werten und werden häufig verwendet, um Zusammenhängen auf die Spur zu kommen.
In [31]:
x1 = [2,2.5,3, 3.4,4.7,5.1,6.5,7.1]
y1 = [2,2.2,3.3,3.7,4.2,5.1,6.4,8.7]
plt.scatter(x1,y1)
plt.show()
In [32]:
x2 = np.random.randn(1000)
y2 = np.random.randn(1000)
plt.scatter(x2, y2);
plt.show()
In [33]:
x1 = [2,1.5,0.3,1.4,2.7,-1.1,-2.5,-2.1]
y1 = [2,1.2,0.33,1.7,2.2,-1.1,-2.4,-2.7]
x2 = np.random.randn(500)
y2 = np.random.randn(500)
plt.scatter(x2,y2,marker="o",color="blue",s=3)
plt.scatter(x1,y1,marker="s",color="red", s=10)
plt.show()
Seaborn ist eine Visualisierungsbibliothek auf der Basis von Matplotlib, die aber in vielerlei Hinsicht das Arbeiten sehr vereinfacht, da vernünftige Ausgangswerte verwendet werden und nicht alle Details mühsam mit der Hand eingegeben werden müssen. Außerdem funktioniert Seaborn gut im Zusammenspiel mit Pandas.
Im folgenden laden wir das Datenset 'Tips' (Trinkgelder), um damit ein wenig herumzuspielen.
In [49]:
import seaborn as sns
import pandas as pd
# load data
tips = sns.load_dataset("tips")
In [4]:
print(type(tips))
print(len(tips))
tips.head()
Out[4]:
In [16]:
sns.distplot(tips.total_bill);
In [23]:
sns.distplot(tips.total_bill, bins=30, rug=True);
In [19]:
a = sns.boxplot(x="total_bill", data=tips);
In [20]:
sns.violinplot(x = "total_bill", data=tips);
In [21]:
plt.figure(figsize=(14,8))
sns.regplot(x="total_bill", y="tip", data=tips, fit_reg=False );
In [22]:
plt.figure(figsize=(14,8))
sns.regplot(x="total_bill", y="tip", data=tips, fit_reg=True );
In [27]:
sns.jointplot(x="total_bill", y="tip", data=tips, size=8);
In [39]:
tips.head()
Out[39]:
In [47]:
g = sns.FacetGrid(tips, col="time", row="day", margin_titles=True, size=3)
g.map(sns.plt.scatter, "total_bill", "tip" );
In [46]:
sns.jointplot(x="size", y="tip", data=tips, size=8);
Interessanter als der absolute Wert für das Trinkgeld ist die Höhe des Trinkgelds im Verhältnis zur Gesamtsumme. Fügen wir eine entsprechende Spalte unserem Datensatz hinzu:
In [51]:
tips['tip_perc'] = tips.tip/(tips.total_bill / 100)
In [52]:
sns.jointplot(x="total_bill", y="tip_perc", data=tips, size=8);
In [58]:
g = sns.FacetGrid(tips, col="sex", row="smoker", margin_titles=True, size=4)
g.map(sns.plt.scatter, "total_bill", "tip_perc" );
In [59]:
sns.jointplot(x="size", y="tip_perc", data=tips, size=8);