Schlagwort-Archive: Tufte

Schoenere Karten mit R und ggplot2

Vor einiger Zeit hatte ich hier schon einmal beschrieben, wie sich mit R einfache Karten und Visualisierungen herstellen lassen. Das geht natuerlich noch deutlich komplexer — aber eben auch schoener. Edward Tufte sollte eigentlich allen ein Begriff sein, die sich mit Visualisierung und grafischer Aufbereitung von Information beschaeftigen; „The Visual Display of Quantitative Information“ empfehle ich immer wieder gerne (Amazon-Affilliate-Link; alternativ ISBN 0961392142).

Neben Tufte gibt es noch ein weiteres grosses Werk, auf das ich bei der ganzen Kartiererei in R gestossen bin: „The Grammar of Graphics“ (Amazon-Affilliate-Link, alternativ ISBN 0387245448). „Gestossen“ ist hier weit ausgelegt, ich habe das Buch nicht einmal gelesen. Ich kenne aber die auf ihm basierende R-Library ggplot2, die die Grammar of Graphics fuer ihre Plots verwendet — und sie dabei aesthetisch ansehlich werden laesst.

Ich verwende im folgenden Beispiel wieder das ESRI-Shapefile der Stadt mit den integrierten Altersquotienten pro Stadtviertel. Prinzipiell laesst sich hier noch viel mehr machen, naemlich auch mit Daten aus Drittquellen. Dazu komme ich in einem spaeteren Post.

Zuerst holen wir uns einige Bibliotheken, setzen das Arbeitsverzeichnis und lesen das Shapefile ein. Ich binde in diesem Tutorial die Libraries immer erst dann ein, wenn eine ihrer Funktionen zum Einsatz kommt. Ich hoffe, so ist halbwegs nachzuvollziehen, was wozu gehoert. Die rgdal-Library erfordert PROJ.4, das einige Zeit lang in Debian und seinen Derivaten in einer kaputten Version daher kam; unter Ubuntu lohnt hier ein Blick auf UbuntuGIS.

library(sp)
library(rgdal)
setwd("/media/home/opendata/altersquotient")
ulm <- readOGR(".", "G_Altersquotient_311210")

Mit einem Blick in die ersten Zeilen des Datenteils unseres Shapefiles faellt auf, dass die Codierung (wieder) etwas gelitten hat. Das laesst sich durch Konvertierung und Ueberschreiben der urspruenglichen Spalten beheben.

head(ulm@data)
ulm@data$STT_Name <- iconv(ulm@data$STT_Name, "ISO_8859-1", "UTF-8")
ulm@data$STTV_Name <- iconv(ulm@data$STTV_Name, "ISO_8859-1", "UTF-8")

Im Folgenden trennen wir den Datenteil vom eigentlichen Shape und wandeln letzteres in Koordinatenreihen um. Um hinterher die einzelnen Teile wieder sinnvoll zusammenfuehren zu koennen, verpassen wir dem ulm-Objekt eine Spalte id, die einfach der Zeilennummer entspricht. Anschliessend speichern wir den Datenteil von ulm nach ulm.df

ulm@data$id <- rownames(ulm@data)
ulm.df <- as.data.frame(ulm)

Die bekannte Library maptools hilft uns nun mit seiner fortify()-Methode, aus dem Shapefile Koordinatenreihen zu machen. Leider ist das nicht so ganz GNU-konform, so dass wir erst einmal mit gpclibPermit() die Erlaubnis geben muessen, diese Teilfunktion auch zu benutzen. (Danke an diese Tutorials und Beispiele, die mich auf die Sache mit dem fortify() gebracht haben)

library(maptools)
gpclibPermit()
ulm_fort <- fortify(ulm, region="id")

Nun muessen ulm.df und ulm_fort wieder zu einem gemeinsamen Data Frame kombiniert werden. Das uebernimmt die join()-Funktion aus der plyr-Library, die wie ein SQL-Join funktioniert. Bei komplexeren Verknuepfungen sollte man das im Kopf behalten und gegebenenfalls explizit einen left oder right oder inner join machen, um nicht zu verzweifeln 😉

Wichtig ist natuerlich, dass beide Teile eine gemeinsame Spalte haben, anhand derer sie verbunden werden koennen. Mit einem head() sehen wir, dass das wunderbar der Fall ist.

library(plyr)
head(ulm.df)
head(ulm_fort)

ulm_merged <- join(ulm_fort, ulm.df, by=“id“)

Nun wird geplottet — mit dem altbekannten RColorBrewer und der ggplot2-Library. Wir fuegen hinzu:

  • Eine Aesthetikangabe: Welche Werte sollen fuer x, y und die Fuellung der Flaechen verwendet werden? Wir faerben anhand des Altersquotienten ein.
  • Die Angabe, aus den Koordinatenreihen Polygone zu zeichnen
  • Zusaetzlich weisse Umrisse um die Stadtviertel
  • Eine Farbskala fuer die Altersquotientenfuellung. colours = brewer.pal(9,“Greens“) wuerde schon reichen, dann gaebe es aber nur fuenf Abstufungen. Stattdessen definieren wir die breaks in Zehnerabstaenden, indem wir einen geeigneten Vektor uebergeben.

library(ggplot2)
library(RColorBrewer)
ggplot(ulm_merged) +
aes(long, lat, group=group, fill=ALTQU) +
geom_polygon() +
geom_path (color="white") +
scale_fill_gradientn(colours = brewer.pal(9, "Greens"), breaks = c(10, 20, 30, 40, 50, 60, 70, 80, 90)) +
coord_equal()

Et voila — eine wunderbare Karte mit schoenem, unaufdringlichem Gitternetz und abgesetztem Hintergrund 🙂

R ist jedoch nicht „nur“ dazu da, bunte Karten zu plotten, zumal ohne raeumlichen Bezug und (in diesem Fall) im Gauss-Krueger-Koordinatensystem. Die hier verwendeten Libraries koennen jedoch noch viel mehr: Komplexe Kombinationen von Daten, und vor allem auch die Ausgabe in verschiedensten Formaten. Google Fusion Tables? GeoJSON? Kein Problem.

Mehr dazu irgendwann demnaechst 😉

Gute und schlechte Visualisierungen

Seit ein paar Tagen geht eine Serie von Infografiken durchs Netz, die offenbar jede Menge Design-Awards gewonnen hat, und ich muss mich fragen: Warum eigentlich? (Hat sie das ueberhaupt?) Im Wesentlichen soll dargestellt werden, wie die Welt aussaehe, wenn man die komplette Weltbevoelkerung mit 100 Personen repraesentieren wuerde. Das ist eigentlich ganz nett, und der Vergleich ist schoen — man moege das aber richtig machen.

Snopes.com beschaeftigte sich bereits ausfuehrlich mit der E-Mail-Variante der 100-Personen-Reduktion und stellt richtigerweise fest, dass die dargestellten Begrifflichkeiten teilweise sehr schwammig sind: Ab wann ist jemand „weiss“, ab wann „nicht-weiss“? Kann man die gesamte Bevoelkerung einfach auf hetero- und homosexuelle Menschen herunterbrechen? Wo sind die B und T aus LGBT?

Davon einmal abgesehen, finde ich die Visualisierung der Zahlen (woher auch immer sie kommen) an sich alles andere als preiswuerdig. Schauen wir uns beispielsweise den Energieverbrauch an:

Kann man die Werte aufgrund der Grafik tatsaechlich in Relation setzen? Ausfuehrlich ohne die Beschriftung (die ich hier fieserweise mal wegeditiert habe)? Nicht wirklich, die Form ist zwar huebsch anzusehen, an sich aber ueberhaupt nicht interpretierbar. Insbesondere, weil die Beschriftung von 76% und 24% spricht — eine kurz ueberschlagene Pixelzaehlung aber ganz andere Zahlen ergibt.

Richtig abstrus wird es dann aber bei manchen anderen Darstellungen:

Hae? Wie viele Leute haben denn nun keinen Zugang zu sauberem Wasser? Nur die, die durch den sichtbaren Teil der Wolke repraesentiert werden? Oder geht die Wolke (so wie Wolken das oft tun) perspektivisch hinter der „sauberen“ Wolke weiter? Was soll das?

Ernsthaft? Come on…

Gut, das hat Unterhaltungswert. Wer sich ernsthaft mit (tatsaechlich praktischen) Informationsvisualisierungen beschaeftigen moechte, kann die Standardwerke von Edward Tufte, naemlich „The Visual Display of Quantitative Information“ und „Envisioning Information“ (Amazon-Referrerlinks) lesen und bekommt dort auch die genaue Erklaerung, warum Visualisierungen wie die von Ng als eigentliche Visualisierung (d.h. auch ohne Legende) eigentlich nichts taugen.

Und nochmal die Tutorenstellen

Guido hat — zu Recht — nachgefragt, wie es denn mit dem Betreuungsverhaeltnis Hilfskraefte/Studierende aussehen wuerde. Mittlerweile habe ich auch eine Uebersicht des Studiendekanats, wie viele Hilfskraefte in den vergangenen Jahren eingestellt worden sind, so dass sich der folgende Graph ergibt:

Diese Auswertung ist mit grosser Vorsicht zu geniessen. Die Zahl der HK-Stellen ist in meiner Quelle naemlich immer nur fuer ein volles Jahr gegeben, wobei mir nicht klar ist, welcher Zeitraum genau gemeint ist. Ich habe demnach jeweils die Haelfte der Tutorenstellen fuer das WS und das SS veranschlagt, wohl wissend, dass das nicht sein kann — alles andere waere aber Glaskugelschauerei. Auch die zu erwartende Studierendenzahl fuer das SS10 steht noch in den Sternen, ich habe einfach grob die Zahlen des WS verwendet.

Ablesen laesst sich aber trotzdem, dass das Betreuungsverhaeltnis nach Einfuehrung der Studiengebuehren (SS07) langsam, im SS08 dann recht stark verbessert wurde — und nun wieder nur unwesentlich ueber dem „alten“ Verhaeltnis liegen wird.

Zusammenfassend heisst das fuer 2010:

  • So wenige Hilfskraefte wie nie* zuvor
  • So wenig Hilfskraftausgaben wie nie* zuvor
  • Das Betreuungsverhaeltnis ist nur geringfuegig besser als vor Einfuehrung der Studiengebuehren — und das bei jaehrlich 1000 EUR pro Studenten „zur Verbesserung der Lehre“

* Soweit mir bekannt — Aufzeichnungen liegen bis 2004 vor