Jakob Richter

ggplot – eine Einführung

Wie funktioniert das mit ggplot? Ich schwärme ja oft von diesem tollen Packet, wie vermutlich fast jeder, der ggplot (genauer ggplot2) kennen und nutzen gelernt hat. Doch für Einsteiger ist die Struktur oft zuerst verwirrend und der Aufwand scheint nicht den Nutzen wert zu sein. Von dem Gegenteil möchte ich euch nun jedoch überzeugen, gerade auch, weil sich der Aufwand am Ende doch erheblich reduzieren kann.

Die Vorteile von ggplot2:

  • schönere Optik
  • Grafiken können leicht an neue Bedürfnisse angepasst werden
  • Exploration von Daten mit wenig Code und bereits druckfertigen Ergebnissen
  • Erscheinungsbild mit wenig Code sauber veränderbar
  • Viele bereits mitgelieferte Plot-typen

Nachteile:

  • gewisse Einarbeitungszeit
  • Daten für ggplot2 Vorbereiten manchmal unintuitiv


Zuerst sollte man verstehen, wie die Daten vorliegen sollten, damit ggplot seine Arbeit zuverlässig tut. Dazu folgender Grundsatz:

Jeder Datenpunkt eine Zeile!

In einem data.frame (es muss immer ein data.frame sein) muss jede Zeile einen Datenpunkt in unserem Plot widerspiegeln. Wenn also zu einem Merkmalsträger mehrere Daten vorliegen die auf einer Achse liegen sollen haben wir zunächst einmal ein kleines Problem. Dazu aber später mehr.
Wenn also jede Zeile einen Datenpunkt enthält, welche Spalten soll es denn geben? Hier liegen die großen Stärken von ggplot2: Fast jeder Spalte kann eine „grafische Interpretation“ zugewiesen werden. Betrachten wir folgendes Beispiel:

Hier ein Beispieldatensatz und wie wir ihn darstellen wollen.


Hier wird schnell klar, dass, wenn wir das mit den Standardmitteln von R umsetzen wollen würden, vor allem das Einfärben ein wenig lästige Codearbeit darstellen würde. Dann bräuchten wir ja auch noch eine Legende und was ist, wenn später noch eine Stadt mit einer anderen Regierung hinzukommen würde. Dann müsste man vermutlich noch mal ein Wenig am Code rumfummeln. Unschön!
Mit ggplot2 geht das natürlich in Sekunden! Trotzdem schauen wir uns es erstmal ganz langsam an:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
install.packages("ggplot2") # Installiert das Packet
library("ggplot2") # Lädt das Packet
 
staedte <- "Stadt;Einwohner;Fläche in km2;Schulden in Mrd;Regierung
Berlin;3499879;891,85;64,03;SPD und CDU
Dortmund;580444;280,71;2,16;SPD
München;1353186;310,43;0;SPD
Hamburg;1799144;755,264;24,9;SPD
Stuttgart;606588;207,36;2,8;CDU"
 
stadtdaten <- read.table(textConnection(staedte), sep=";", head=T, dec=",")
head(stadtdaten)
# Wir sehen, dass die Spaltennamen keine Leerzeichen mehr enthalten.
# Die Spaltennamen sind gleich noch wichtig.

Bis hierhin alles also recht klar. Nun kommen wir dorthin, wo die Magie geschieht:

16
17
18
19
20
g <- ggplot(stadtdaten,
            aes(x=Einwohner,
                y=Fläche.in.km2,
                size=Schulden.in.Mrd,
                color=Regierung))

Was geschieht hier? g wird das neue ggplot-Objekt. Hier kommt alles rein, was wir plotten wollen. Initialisiert wird es stets mit ggplot(). Meistens wird man jedoch noch zwei Parameter angeben: An erster Stelle steht der Datensatz (hier: stadtdaten), aus dem ggplot die Informationen ziehen soll. Das zweite Argument ist die Funktion aes(). Diese wertet jede Zeile des Datensatzes aus und ihr kann wiederum vorgegeben werden, welche Spalte wie dargestellt werden soll. Die Nutzung von aes() stellt auch die Beschriftung der Achsen und der Legende sicher.
Jetzt muss dem ggplot Objekt noch gesagt werden, wie es zu plotten ist. Am sinnvollsten erscheint es die Daten als Punkte darzustellen:

21
22
g <- g + geom_point()
g

geom_point() muss kein weiteres Argument übergeben werden, da bereits alle notwendigen Angaben durch aes() in g stehen. Da g jetzt weiß, wie es zu plotten ist können wir es einfach mit dem Aufruf g plotten.
So sieht das Ergebnis aus:

Noch nicht besonders toll. Die Punkte sind viel zu klein und zuerst einmal würden wir gerne wissen welche Stadt nun welcher Punkt ist. Das ist überhaupt kein Problem! geom_text() macht alles.

24
25
g + geom_text(aes(label=Stadt))
g

Wir erinnern uns: g wurden bereits gesagt, dass es ein Punkteplot werden soll. Jetzt kommt das so genannte Geom (geometric object) geom_text() hinzu. Das Geom braucht jedoch zwingend noch ein Argument, welches ihm sagt, welcher Text denn jeweils gedruckt werden soll. Dieses regelt wieder aes().
Doch was ist nun passiert?!

Wie bereits erwähnt gilt das ganz am Anfang in ggplot() geschriebene aes() für alle Dinge die zu g hinzugefügt werden. Und so bedient sich auch das geom_text() der Farben und Größen, welche wir anfangs bestimmt haben. Häufig wollen wir das auch. Zumindest für die x und y-Koordinaten und hier vielleicht auch für die Farbe. Also müssen wir die Eigenschaften trennen, je nachdem ob sie mit zum Text oder zu den Punkten gehören sollen und nur die gemeinsamen Eigenschaften schreiben wir in die allgemeinen Aesthetics (aes()).
Also noch mal von vorn:

27
28
29
30
31
32
g2 <- ggplot(stadtdaten,
             aes(x=Einwohner,
                 y=Fläche.in.km2,
                 color=Regierung))
g2 <- g2 + geom_point(aes(size=Schulden.in.Mrd))
g2 + geom_text(aes(label=Stadt))


Immer noch nicht das Gelbe vom Ei. Die Schrift braucht rechts und links irgendwie mehr Platz. Das geht wie folgt:

34
35
36
g2 <- g2 + scale_x_continuous(expand=c(0.2,0)) +
           scale_y_continuous(expand=c(0,60))
g2 + geom_text(aes(label=Stadt))

Nun haben wir die x-Achse links und rechts um 20% ihrer ursprünglichen Breite erweitert. Die y-Achse geht nun 60 Einheiten weiter nach oben und unten. Man kann in expand() auch beides Kombinieren. Die erste Zahl ist ein Faktor und die zweite eine Konstante.

Immer noch nicht perfekt. Der Text sollte nicht so auf den Punkten kleben.

38
g2 + geom_text(aes(label=Stadt),vjust=-0.6)

Wichtig ist zu beachten, dass vjust und hjust offiziell nur die Werte 0,0.5,1 unterstützt. Mehr Möglichkeiten zum modifizieren des Text-Geoms findet man auf der offiziellen ggplot2 Hilfe.

So sieht es doch schon fast brauchbar aus. Jetzt wäre es jedoch super, wenn die Skalen etwas schöner wären und überhaupt alles:

40
41
42
43
g2 <- g2 + scale_y_continuous(trans="log2", expand=c(0,0.22)) +
  #mit trans funktioniert expand etwas merkwürdig, neuanpassung notwendig
           scale_size_continuous(trans="sqrt",range=c(3,10), breaks=c(0,10,30,60))
g2 + geom_text(aes(label=Stadt,vjust=-0.5-sqrt(Schulden.in.Mrd/80)))

Mit trans="" können die Achsen transformiert werden. Das Schöne ist, dass auch die Koordinatengitter sich anpasst, sodass die Transformation auf den ersten Blick sichtbar ist. Mögliche Transformationen sind u.a: log, log2, sqrt, exp, log10.
Mit scale_size_continuous() wird die Größenskala angepasst. trans="log" kann hier nicht verwendet werden, da München nicht verschuldet ist. Mit range=c(3,10) wird festgelegt, dass der kleinste Punkt die Größe 3 und der größte die Größe 10 haben soll. breaks=c(0,10,30,60) lässt uns die Möglichkeit manuell anzugeben, welche Größen in die Legende gepackt werden. Oft liefert da die Automatik von ggplot nicht die besten Ergebnisse.
Ein kleiner Trick ist auch in geom_text() enthalten: Wichtig ist zu merken, dass bei ggplot fast alle Plottingeigenschaften sowohl in den Aesthetics als auch außerhalb stehen können. Stehen sie Außerhalb gelten sie für alle Elemente des Geoms pauschal und werden nicht in die Legende übernommen. Innerhalb von aes() werden sie für jede Zeile in dem Datensatz angewendet. Wenn man dies Verinnerlicht hat man schon eine der wichtigsten ggplot-Eigenschaften verstanden und kann damit gut arbeiten. In diesem Beispiel heben wir so den Text abhängig von der jeweiligen Punktgröße (die Schulden) weiter über die ursprüngliche Position.

Auch wenn das jetzt viel Text war, hoffe ich, dass ihr die Grundsätze von ggplot2 verstanden habt und somit auch die sehr hilfreichen und zahlreichen Beispiele auf der offiziellen Seite besser nachvollziehen könnt.

One Comment

  1. Corinna sagt:

    Sehr geehrter Herr Richter,
    ich studiere an der FOM in Dortmund und schreibe zur Zeit eine Seminararbeit im Fach Empirisches Finance & Accounting. Mein Thema: Unternehmensskandale und Aktienkurse – eine Event Study Analysis am Beispiel der MLP AG.
    Ich möchte gerne in meiner Seminararbeit 3 Grafiken (untereinander!) zeigen. Mir wurde ggplot2 empfohlen und meine Befehle lauten wie folgt:
    # 1. Graph zeichnen –> kumulierte Renditen im Schätzfenster

    ggplot(data=schaetz, aes(x=Datum)) + geom_line(aes(y=KumulierteRendite_MLP, col =“blue“)) +
    geom_line(aes(y=KumulierteRendite_BM, col=“red“)) +
    ylab(„Kumulierte Rendite“) +
    xlab(„Monat“) +
    ggtitle(„kumulierte Renditen im Schätzfenster Mai 2001 bis Mai 2002″) +
    scale_colour_manual(name = ‚Werte‘, values =c(‚blue’=’blue‘,’red’=’red‘), labels = c(‚MLP‘,’CDAX‘))
    scale_x_date(breaks = c(event_day, event$Datum[15], event$Datum[30] ))

    # 2. Graph zeichnen — > kumulierte Renditen im Eventfenster

    ggplot(data=event, aes(x=Datum)) + geom_line(aes(y=KumulierteRendite_MLP, col =“blue“)) +
    geom_line(aes(y=KumulierteRendite_BM, col=“red“)) +
    ylab(„Kumulierte Rendite“) +
    xlab(„Monat“) +
    ggtitle(„kumulierte Renditen im Eventfenster Mai 2002 – Juli 2002 „) +
    geom_vline(xintercept = as.numeric(event_day), col=“green“) +
    scale_colour_manual(name = ‚Werte‘, values =c(‚blue’=’blue‘,’red’=’red‘), labels = c(‚MLP‘,’CDAX‘))
    scale_x_date(breaks = c(event_day, event$Datum[15], event$Datum[30] ))

    # 3. Graph zeichnen –> abnormale Rendite im Eventfenster

    ggplot(data=event, aes(x=Datum)) + geom_line(aes(y=AbnormaleRendite, col =“blue“)) +
    ylab(„abnormale Rendite“) +
    xlab(„Monat“) +
    ggtitle(„abnormale Renditen im Eventfenster Mai 2002 – Juli 2002 „) +
    geom_vline(xintercept = as.numeric(event_day), col=“green“) +
    scale_colour_manual(name = ‚Werte‘, values =c(‚blue’=’blue‘,’red’=’red‘), labels = c(‚MLP‘,’CDAX‘))
    scale_x_date(breaks = c(event_day, event$Datum[15], event$Datum[30] ))

    Leider bekomme ich es nicht hin, dass er mir die 3 Grafiken untereinander macht. Alternativ wollte ich gerne versuchen, dass er die x-Achse verkleinert, damit die Bewegungen nicht so extrem sind.

    Können Sie mir helfen?
    Über eine Rückmeldung würde ich mich sehr freuen.

    Gruß
    C. Schäfer

Leave a Reply