Jakob Richter

ggplot2 – ein umfangreiches Beispiel

Das Einführungsbeispiel war ja in Punkto Datenumfang sehr bescheiden. Seine stärke spielt ggplot2 vor allem bei großen Datensätzen mit vielen Merkmalen aus. Insbesondere, wenn man noch nicht weiß wo es hingehen soll.

Einen Datensatz entdecken

Aus der Umweltprobenbank habe ich mir mal diesen Datensatz zusammengestellt. Ich weiß auch nur, dass es um die Bodenbelastungen an verschiedenen Orten in Deutschland geht. Einen tieferen Einblick in die Daten gewinnt man mit bloßen Augen nicht so recht.

Ein kleiner Einblick mit Excel in den Datensatz



Lesen wir diese Datei nun mit R ein.

1
2
3
dat <- read.table("upb_chemical_pollution_data.csv", head=T, sep="\t", dec=",")
dat <- dat[dat$Statistischer.Parameter=="Arithmetischer Mittelwert",] #Wir interessiern uns nur für die Mittelwerte
head(dat)

Ein Blick auf den Anfang des Datensatzes verrät, dass R die Zahlen der Spaltennamen um ein vorangestelltes X erweitert hat. Das muss später noch bereinigt werden. Außerdem interessieren wir uns nur für die Zeilen, die den Arithmetischen Mittelwert der Messungen beinhalten (Zeile 2).

Daten umformen mit melt()

Wichtig für ggplot (wir erinnern uns) ist, dass jeder Punkt des Plots durch eine Zeile im Datensatz repräsentiert wird. Natürlich soll jedes Jahr ein eigenen Datenpunkt darstellen. Dazu muss für jede Zeile des Datensatzes der Bereich mit den Jahreszahlen transponiert werden, sodass die Jahreszahlen dann eine Spalte bilden. Die Werte aus der ursprünglichen Zeile gelten für alle Jahre, also werden sie in die neu entstandenen Zeilen kopiert. Das klingt kompliziert, aber mit der Funktion melt() aus dem Paket reshape() (Hinweis: In älteren Versionen von ggplot2 war melt() noch enthalten) geht es im nu.

5
6
7
8
mdat <- melt(dat, measure.vars=8:24,
                  id.vars=c("Probenart","Analyt","Messeinheit"),
                  variable_name="Jahr", na.rm=T)
head(mdat)

In den Spalten 8 bis 24 stehen die Jahre mit ihren Messwerten (measure.vars=8:24. Das sind also die Spalten die in Zeilen transponiert werden sollen. Der Name für die so neu entstandene Spalte ist mit variable_name="Jahr" festgelegt. Die jahresunabhänigen Merkmale die uns interessieren sind gegeben durch id.vars=c("Probenart","Analyt","Messeinheit"). Ist ein Messwert nicht vorhanden, so soll keine Zeile enstehen (na.rm=T).

Hinweis zu melt(): In der Regel genügt die Angabe von id.vars= oder measure.vars=. Es werden dann jeweils die übrigen anderen Spalten als measure.vars bzw. id.vars verwendet. Angaben können sowohl über Spaltenindizes als auch über Spaltennamen erfolgen.

Nun noch schnell das X vor der Jahreszahl entfernen:

9
mdat$Jahr <- as.numeric(substr(mdat$Jahr,start=2,stop=5)) #nur Zeichen 2 bis 5 werden genommen

Nun lassen wir die Magie passieren:

11
12
g <- ggplot(mdat,aes(y=value,x=Jahr))
g  + geom_point(aes(color=Probenart))


Gut – das war sehr basic. Bereits hier erkennt man, dass in Regenwürmern der Wert der Schadstoffkonzentration sehr hoch ist. Sie scheinen sich also gut zu eignen um Schadstoffe im Boden ausfindig zu machen. Interessant! Also das Leute das überhaut machen.
Jetzt stellt sich die Frage: Lässt sich denn ein Trend erkennen? Wie wäre es mit einer polynomiellen Regression?

14
15
g + geom_point(aes(color=Probenart)) +
    stat_smooth()

Polynomielle Regression
Hat sich der Schadstoffanteil im Boden also seit 1995 verbessert? Das ist alles noch ein wenig undifferenziert. Wir sollten die Regression nach den verschiedenen Schadstoffen unterteilen.

17
18
g + geom_point(aes(color=Probenart)) +
    stat_smooth(aes(group=Analyt, fill=Analyt),color="black")

Polynomielle Regression nach Schadstoffen unterteilt
Ok – offensichtlich wurde der Regenwurm genutzt um den Phosphorgehalt in Boden zu untersuchen. Schwefel wurde wohl im Eiinhalt einer Stadttaube untersucht. Das ist aber sehr Vage formuliert. Wie wäre es denn mit verschiedenen Plots für die unterschiedlichen Stoffe? Das geht mit Hilve von facet_wrap(). Durch die Einteilungen kann auch die Gruppierung bei stat_smooth() weglassen werden. Da die Schadstoffkonzentrationen unterschiedlich gelegen sind darf bei jedem Abschnitt die y-Achse frei sein (scales="free_y"). Mit ncol=1 wird bewirkt, dass die Plots untereinander erscheinen. Darum habe ich auch nicht scales="free" gewählt, denn so bleiben die Jahre richtig untereinander.

20
21
22
23
g <- g + geom_point(aes(color=Probenart)) +
	 stat_smooth() +
         facet_wrap(~Analyt+Messeinheit, scales="free_y", ncol=1)
g

Grafik unterteilt nach Schadstoffen
Das ist doch schon viel übersichtlicher. Da ich mit den Geoms in diesem Plot schon recht zufrieden war hab ich alles mal fest im ggplot-Objekt gespeichert. Denn nun widmen wir uns dem Layout.

Layout eines ggplot-Plots verändern

Jetzt mache ich es mal kurz: Das Ergebnis, der Code und danach die Erläuterung:
ggplot mit verbessertem Layout

25
26
27
28
29
30
31
g + ylab(label="Wert") +
	  opts(legend.position="bottom", title="Bodenproben") +
	  guides(color = guide_legend(ncol = 2,title.vjust=0.2)) +
	  opts(legend.title=theme_text(angle=90, face="bold", size=11),
		plot.title=theme_text(face="bold", size=20,vjust=1)) +
	  scale_x_continuous(minor_breaks = function(x){ceiling(x[1]):floor(x[2])},
	                     breaks = function(x){seq(ceiling(x[1]),floor(x[2]),by=2)})
  • 25: Der Name der y-Achse wird geändert und es wird eine Überschrift hinzugefügt.
  • 26: Wir positionieren die Legende nach unten uns geben ihr einen neuen Titel.
  • 27: Die Gestaltungsführung guides() der Farblegende (color=guide_legend()) wird auf 2 Spalten (ncol = 2) geändert und der Titel ein wenig nach oben verschoben (title.vjust=0.2).
  • 28: In den ggplot-Optionen (opts()) wird der Titel der Legende um 90° gedreht, auf Schriftgröße 11 und dick gedruckt gesetzt.
  • 29: Des weiteren passen wir auch die Schriftart der Überschrift an.
  • 30: Das feine x-Achsengitter wird auf ganze Jahre gelegt …
  • 31: und das grobe Gitter auf alle zwei Jahre.

Fertig!

Leave a Reply