Datenvisualisierung in Python [Tutorial]

Python ist eine der wichtigsten Programmiersprachen in der Data Science Szene. Der Einstieg in diese Programmiersprache fällt zum Beispiel im Vergleich zur Programmiersprache R etwas einfacher, da Python eine leicht zu verstehende Syntax hat. Was jedoch beim Einstieg zur größeren Hürde werden kann, ist der Umgang mit den unüberschaubar vielen Bibliotheken. Die wichtigsten Bibliotheken für Data Science / Data Analytics stellte ich bereits in diesem Artikel kurz vor. Hier ist es wichtig, einfach erstmal anzufangen – Warum nicht mit den ersten Datenvisualisierungen?

Natürlich gibt es sehr viele tolle und schön anzusehende Visualisierungen, die teilweise sehr speziell sind. In einem anderen Artikel stellte ich beispielsweise die 3D-Visualisierung von Graphen mit Python und UbiGraph vor. Dieser Artikel hier gilt aber vor allem Einsteigern, die erste Diagramme hergezaubert bekommen möchten.

Damit wir beginnen können, müssen im Python-Skript zuerst zwei wichtige Bibliotheken eingebunden werden:

import matplotlib.pyplot as pyplot

import pandas as pandas

Beide Bibliotheken können direkt gedownloaded werden, sind aber auch im Anaconda Framework enthalten (Empfehlung: Anaconda für Python 2.7).

Die Bibliothek matplotlib (library) ist mit Sicherheit die gängigste zur Visualisierung von Daten. Die Bibliothek pandas ist eine der verbreitetsten, die für den Zugriff, die Manipulation und Analyse von Daten eingesetzt wird. In diesen einfachsten Beispielen benutzen wir pandas nur zum Zugriff auf Daten.

Für die Visualisierung benötigen wir natürlich auch ein Beispiel-Dataset (Tabelle). Eine solche kann sich jeder selber erstellen, wer die nachfolgenden Code-Beispiele aber nachstellen möchte, kann diese Daten verwenden:

ID|Standort|Funktion|Mitarbeiter|Umsatz|Kosten 
1|Muenchen|Verwaltung + Vertrieb|45|3500000|2300000 
2|Stuttgart|Nur Vertrieb|23|2800000|800000 
3|Hannover|Verwaltung + Vertrieb|45|1800000|1000000 
4|Leipzig|Nur Vertrieb|12|1000000|320000 
5|Dresden|Produktio + Vertrieb|65|450000|700000 
6|Frankfurt am Main|Nur Vertrieb|12|240000|20000 
7|Duesseldorf|Nur Vertrieb|43|45000|53000 
8|Kassel|Nur Vertrieb|23|250000|90000 
9|Hamburg|Verwaltung + Vertrieb|89|2800000|690000 
10|Koeln|Nur Vertrieb|21|110000|12000 
11|Potsdam|Nur Vertrieb|12|20000|67000 
12|Nuernberg|Nur Vertrieb|15|60000|30000 
13|Ingolstadt|Nur Vertrieb|8|80000|10000 
14|Wolfsburg|Nur Vertrieb|8|90000|23000 
15|Braunschweig|Nur Vertrieb|32|900000|750000 
16|Augsburg|Verwaltung + Vertrieb|45|700000|370000 
17|Chemnitz|Nur Vertrieb|4|95000|78000 
18|Bochum|Nur Vertrieb|9|32000|67000 
19|Dortmund|Produktio + Vertrieb|56|2100000|450000
20|Essen|Nur Vertrieb|10|190000|140000

Diese 20 Zeilen können einfach via Copy + Paste in eine Datei kopiert werden, die dann als data-science-blog-python-beispiel.txt abgespeichert werden kann.

Der Zugriff von Python aus erfolgt dann mit pandas wie folgt:

dataset = pandas.read_csv(“data-science-blog-python-beispiel.txt”, sep=”|”, header=0, encoding=”utf8″)

Kreisdiagramm

Ein Kreisdiagramm (Pie Chart) lässt sich basierend auf diesen Daten beispielsweise wie folgt erstellen:

kreisdiagramm

# Pie Chart
var= dataset.groupby(['Funktion']).sum().stack()
temp = var.unstack()
type(temp)
x_list = temp['Mitarbeiter']
label_list = temp.index
pyplot.axis("equal") # Kreisdiagramm rund gestaltet (sonst Standard: oval!)
pyplot.pie(x_list, labels=label_list, autopct="%1.1f%%")
pyplot.title('Aufteilung alle Mitarbeiter auf die Standorte nach Funktion')
pyplot.show()

Balkendiagramm

Balkendiagramme können einfachste Größenverhältnisse aufzeigen.

balkendiagram

var = dataset.groupby('Funktion').Umsatz.sum()
fig = pyplot.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('Funktion')
ax.set_ylabel('Umsatz in Summe')
ax.set_title('Umsatzvolumen nach Funktion der Filialen')
var.plot(kind='bar')
pyplot.show()

Gestapeltes Balkendiagramm

Mit nur wenig Erweiterung wird aus dem einfachen Balkendiagramm ein gestapeltes.

balkendiagram-gestapelt

var = dataset.groupby(['Funktion', 'Standort']).Umsatz.sum()
var.unstack().plot(kind='bar', stacked=True, grid=True)
pyplot.legend(bbox_to_anchor=(1.09, 1), loc=0, borderaxespad=0.5)
pyplot.show()

Histogramm (Histogram)

Histogramme sind ein wichtiges Diagramm der Statistik, mit dem sich Verteilungen aufzuzeigen lassen.

histogramm

# Histogramm
fig = pyplot.figure()
ax = fig.add_subplot(1,1,1)
ax.hist(dataset['Mitarbeiter'], bins=5, color='#9400D3')
pyplot.title('Mitarbeiter Verteilung')
pyplot.xlabel('Verteilung')
pyplot.ylabel('Anzahl Mitarbeiter')
pyplot.show()

Lininediagramm

Der Beispieldatensatz gibt kein gutes Szenario her, um ein korrektes Liniendiagramm darstellen zu können; aber dennoch hier ein How-To für ein Liniendiagramm:

line-diagam

#Line Chart
var = dataset.groupby('Standort').Umsatz.sum()
fig = pyplot.figure()
ax1 = fig.add_subplot(1,1,1)
ax1.set_xlabel('Umsatz')
ax1.set_ylabel('Standort')
var.plot(kind='line')
pyplot.show()

Kastengrafik (Box Plot)

Ein Box Plot zeigt sehr gut Schwerpunkte in einer Verteilung.

box-plot-diagam

fig = pyplot.figure()
ax = fig.add_subplot(1,1,1)
ax.boxplot(dataset['Mitarbeiter'])
pyplot.show()

Punktverteilungsdiagramm (Scatter Plot)

punktdiagramm

fig = pyplot.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(dataset["Mitarbeiter"], dataset["Umsatz"])
ax.set_xlabel('Anzahl Mitarbeiter')
ax.set_ylabel('Umsatz')
pyplot.show()

Blasendiagramm (Bubble Chart)

Das Punktdiagramm kann leicht durch hinzufügen einer dritten Dimension zu einem Bubble-Chart erweitert werden. In dieser Darstellung mit logarithmischen x-/y-Achsen (log).

bubblechart

fig = pyplot.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(dataset['Kosten'], dataset['Umsatz'], s=dataset['Mitarbeiter'])
ax.set_xlabel('Umsatz')
ax.set_ylabel('Kosten')
pyplot.xscale('log')
pyplot.yscale('log')
pyplot.show()

 

Extraktion von Software-Metriken aus Java-Dateien mit ANTLR4

In der Software-Entwicklung wird mehr und mehr auf Metriken gesetzt, um den Entwicklungsprozess zu messen und zu verbessern. Tools wie SonarQube und FindBugs helfen dabei – doch sie haben ihre Grenzen. Sie brauchen build-fähige Projekte. Die Metriken sind manchmal nicht genau genug dokumentiert oder lassen sich nur schwer anpassen.

Dabei ist es gar nicht so schwierig, ein eigenes Tool zu schreiben. So können die Metriken selbst definiert, auf Textdateien angewendet, als Skript automatisiert und an beliebige Schnittstellen weitergeben werden – z. B. als CSV-Datei nach R, per Webinterface oder als E-Mail.

Im Folgenden wird gezeigt, wie mit ANTLR4 aus Java-Textdateien Metriken erhoben werden können. Das Beispiel-Projekt steht auf GitHub zur Verfügung.

Statische Code-Analyse mit ANTLR4

ANTLR4 (ANother Tool for Language Recognition) wird seit 1989 von Terence Parr, Professor an der University of San Francisco, entwickelt. Das Tool selbst ist kostenlos; die ausführliche Dokumentation kostet jedoch 27 US-Dollar. Für den Einstieg reicht die kostenlose Dokumentation. ANTLR4 ist eine Java-Bibliothek.

Beim Parsen erstellt ANTLR4 auf Basis einer Grammatik einen Syntaxbaum. Nach dem Parsen wird der Syntaxbaum mit einem Walker abgelaufen. Dabei auftretende Events können über ein Listener-Interface abgefangen werden. Durch das Verarbeiten der Events können eigene Metriken berechnet werden.

Das Listener-Interface selbst wird über die Grammatik spezifiziert. ANTLR4 generiert aus der Grammatik Listener in Java, von denen anschließend geerbt wird.

Für viele Programmiersprachen gibt es bereits fertige Grammatiken, die auf GitHub gemeinsam entwickelt werden (siehe z. B. Java-Grammatik). Ansonsten muss die Grammatik selbst geschrieben werden.

Das Beispiel-Projekt

Im Beispiel wird der Klassenname und die Anzahl von Methoden aus einer Java-Klasse erhoben:

/**
 * A cat is a cat is a cat.
 *
 */

public class Cat {

      private String name;

      private int height;

      public Cat(String name, int height) {

            setName(name);

            setHeight(height);

      }

      public String getName() {

            return name;

      }

      public void setName(String name) {

            this.name = name;

      }

      public int getHeight() {

            return height;

      }

      public void setHeight(int height) {

            this.height = height;

      }
}

Das Ergebnis wird in einer Map<String, Integer> ausgegeben.

Vorbereitungen

Im Beispiel werden Eclipse, ein ANTLR4-Eclipse-Plugin und Maven benutzt. ANTLR4 lässt sich auch unabhängig von Eclipse und Maven benutzen.

Nach der Installation des Eclipse-Plugins muss in der pom.xml eine Dependency ergänzt werden:

<dependency>

<groupId>org.antlr</groupId>

<artifactId>antlr4-maven-plugin</artifactId>

<version>4.5</version>

</dependency>

Die Java-Grammatik wird von GitHub heruntergeladen und unter src/main/antlr4/Java.g4 abgelegt. Anschließend werden per Rechtsklick auf Java.g4 -> Run As -> Generate ANTLR Recognizer die Hilfsdateien von ANTLR4 angelegt.

Damit die Hilfsdateien von Eclipse als Java-Quellcode erkannt werden, werden sie nach src/main/java/generated kopiert.

Metriken definieren

ANTLR4 erstellt aus der Grammatik einen JavaBaseListener. Zum Definieren der Metriken wird ein eigener Listener programmiert, der vom JavaBaseListener erbt. Wenn ANTLR4 später den Syntaxbaum durchläuft, ruft es die entsprechenden Listener-Methoden auf.

/**
* Listens to Events, if ANTLR walks a parse tree.
*
* @author Sven Meyer
*/

public class Listener extends JavaBaseListener {

Im JavaBaseListener sind alle Events, auf die gehört werden kann, als Methode aufgeführt. Um nun den Klassennamen für die Metrik zu erfahren, wird das Event ClassDeclaration abgehört:

/** Listen to matches of classDeclaration */

@Override

public void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx) {

setClazzName(ctx.Identifier().toString());

}

Um die Anzahl der Methoden zu erhalten, wird ein Counter bei jedem Auftreten einer MethodDeclaration erhöht.

/** Listen to matches of methodDeclaration */

@Override

public void enterMethodDeclaration(JavaParser.MethodDeclarationContext ctx) {

methodCount++;

}

ANTLR ausführen

Damit ANTLR ausgeführt werden kann, braucht es noch die zu lesende Datei und den Listener. Dazu sind nur wenige Zeilen Code notwendig:

public Map<String, Integer> extract(File importFile) throws Exception {

/** Prepare input for ANTLR. */

InputStream is = new FileInputStream(importFile.getAbsolutePath());

ANTLRInputStream input = new ANTLRInputStream(is);

JavaLexer lexer = new JavaLexer(input);

CommonTokenStream tokens = new CommonTokenStream(lexer);

JavaParser parser = new JavaParser(tokens);



/** Parse. */

ParseTree tree = parser.compilationUnit();



/** Create standard walker. */

ParseTreeWalker walker = new ParseTreeWalker();



/** Initiate walk of tree with listener. */

Listener listener = new Listener(parser);

walker.walk(listener, tree);



/** Save the results. */

Map<String, Integer> result = new HashMap<>();

result.put(listener.getClazzName(), listener.getMethodCount());

Ein Test prüft, ob der Klassenname und die Methodenanzahl richtig extrahiert werden:

@Test

public void test() throws Exception {

/** Prepare. */

// String = clazzName, Integer = methodCount

Map<String, Integer> result = new HashMap<>();



/** Execute. */

Extractor e = new Extractor();

result = e.extract(new File("src/main/resources/Cat.java"));



/** Test. */

// clazzName should be Cat

assertTrue(result.keySet().contains("Cat"));

// count of methods should be 4

assertEquals(new Integer(4), result.get("Cat"));

}

Die fertige Projektstruktur sieht in Eclipse so aus:

01_projektstruktur

Abbildung 1: Die fertige Projektstruktur.

Nun kann der Test erfolgreich durchgeführt werden.

02_erfolgreicher_test

Abbildung 2: Der Testfall läuft erfolgreich.

 Fazit

Damit der Code produktiv genutzt werden kann, sollten noch mögliche I/O- und ANTLR-Fehler behandelt werden. Außerdem müssen die erhobenen Daten weitergegeben werden, um z. B. als CSV-Datei in R importiert werden zu können.

Erfahrungsgemäß ergeben sich aus dem großen Sprachumfang viele Sonderfälle, die bei der Definition von Metriken berücksichtigt werden müssen. Hier helfen Testfälle weiter, um eine korrekte Messung sicherzustellen.

Das Beispiel konnte zeigen, dass leicht eigene Metriken aus Java-Quellcode erhoben werden können. So werden Quellcode und strukturierte Texte für die Analyse und Optimierung zugänglich.

 

Referenzen & Links

  • ANTLR4
    Die Projektseite von ANTLR4.
  • Java-Grammatik
    Die ANTLR4-Grammatik für die Java-Programmiersprache.
  • Beispielprojekt auf GitHub
    Das in diesem Tutorial verwendete Beispielprojekt auf GitHub.
  • ANTLR4-Eclipse-Plugin
    Das Eclipse-Plugin, das zum Ausführen von ANTLR4 in Eclipse benutzt werden kann.
  • Rascal MPL
    Eine Meta-Programmiersprache. Erlaubt nicht nur die Analyse, sondern auch das Erzeugen + Verändern von Quellcode.
  • Fallstudie Java-Korpus
    Eine laufende Fallstudie des Autors, in der ANTLR4 benutzt wird, um die typische Verwendung von Java-Sprachkonstrukten in 2,8 Mio. Dateien zu untersuchen.

R für Process Mining & Projektmanagement – Literaturempfehlungen

Es gibt immer wieder Skriptsprachen, die neu am IT-Horizont geboren um Anwender werben. Der IT-Manager muß also stets entscheiden, ob er auf einen neuen Zug aufspringt oder sein bisheriges Programmierwerkzeug aktuellen Anforderungen standhält. Mein Skriptsprachenkompass wurde über frühere Autoren kalibriert, an die hier erinnert werden soll, da sie grundsätzliche Orientierungshilfen für Projektplanungen gaben.

Im Projektmanagement geht es stets um aufwandsbezogene Terminplanung, im CAFM-Projektmanagement  z. B. konkret um die Analyse und Schätzung geplanter und ungeplanter Maßnahmen, wie geplante Wartungen oder zufällige technische Störungen im Gebäudemanagement, um Wahrscheinlichkeiten.

Warum löst R die Terminplanung strategisch und praktisch besser als Python, Perl, Java oder etc.? Weil sich geschätzte Ereignisse in Zeitfenstern normalverteilt als so genannte Gaußsche Glockenkurve abbilden, einer statistischen Schätzung entsprechen.

Hier zwei Beispielgrafiken zum Thema Terminschätzung aus aktueller Literatur.

1. Standardnormalverteilung

Praxishandbuch Projektmanagement – inkl. Arbeitshilfen online von Günter Drews, Norbert Hillebrand, Martin Kärner, Sabine Peipe, Uwe Rohrschneider

Haufe-Lexware GmbH & Co. KG, Freiburg, 1. Auflage 2014 – Siehe z. B. Seite 241, Abb. 14 Normalverteilung als Basis von PERT (Link zu Google Books)


Praxishandbuch Projektmanagement – inkl. Arbeitshilfen online

2. Betaverteilung

Projektmanagement für Ingenieure: Ein praxisnahes Lehrbuch für den systematischen Projekterfolg von Walter Jakoby, Hochschule Trier

Springer Vieweg, Springer Fachmedien Wiesbaden 2015, 3, Auflage – Siehe z. B. Seite 215, Abb. 7.13 Beta-Verteilung (Link zu Google Books).


Projektmanagement für Ingenieure: Ein praxisnahes Lehrbuch für den systematischen Projekterfolg 

Eine objektorientierte Statistikprogrammiersprache mit über 7.000 Paketen weltweit lädt ein, nicht jede Funktion neu erfinden zu wollen und macht glaubhaft, dass kein Unternehmen der Welt über derart Programmierwissen und Kapazität verfügt, es besser zu können. Für statistische Berechnungen empfiehlt sich seit Jahren R, für mich spätestens seit 2003. Früheren Autoren war das grundlegend klar, daß deterministische Terminplanungen immer am Mangel stochastischer Methoden kranken. In meiner Studienzeit kursierte an der Martin Luther Universität Halle an der Saale der Witz, es gibt zwei Witze an der landwirtschaftlichen Fakultät, den Badewitz und den Howitz.  Doch das Buch vom Badewitz halte ich bis heute. Im Kapitel 5.3 Elemente der Zeitplanung fand ich dort in Abbildung 5.7 auf Seite 140 erstmals die Wahrscheinlichkeitsverteilung einer Vorgangsdauer als normalverteilte Grafik.

Vgl. Zur Anwendung ökonomisch-mathematischer Methoden der Operationsforschung, federführend Dr. sc. agr. Siegfried Badewitz, 1. Auflage 1981, erschienen im VEB Deutscher Landwirtschaftsverlag Berlin. Ein Grafikkünstler zur schnellen Visualisierung von Funktionen und Dichteverteilungen ist seit Jahren R. Zur R-Umsetzung empfehle ich gern meine R-Beispielbibel bei Xing.

Wer zur Statistik der Terminschätzung tiefer greifen will, kommt an Autoren wie Golenko u. a. nicht vorbei. Badewitz verwies z.B. auf Golenko’s Statistische Methoden der Netzplantechnik in seinem o.g. Buch (Link zu Google Books).


Statistische Methoden der NetzplantechnikHier empfehle ich zum Einstieg das Vorwort, das 2015 gelesen, aktuell noch immer gilt, nicht das Jahr seiner Niederschrift 1968 preisgibt:

Gegenwärtig beobachtet man häufig Situationen, in denen bei der Untersuchung von zufallsbeeinflußten Systemen die in ihnen auftretenden Zufallsparameter durch feste Werte (z. B. den Erwartungswert) ersetzt werden, wonach dann ein deterministisches Modell untersucht wird.

Und hier noch ein Beispiel von Seite 203:

Praktisch kann jede komplizierte logische Beziehung auf eine Kombination elementarer stochastischer Teilgraphen zurückgeführt werden.

Meine Empfehlung für Process Mining und Projektmanagement lautet daher – intelligente Stochstik statt altbackenem Determinismus.