Koordinatensysteme in ggplot2: Leicht übersehen und ziemlich unterschätzt


Alle Plots haben Koordinatensysteme. Vielleicht gerade weil sie ein so integraler Bestandteil von Plots sind, werden sie leicht übersehen. In ggplot2 jedoch gibt es mehrere sehr nützliche Optionen, um die Koordinatensysteme von Plots anzupassen – diese werden wir in diesem Blogpost nicht übersehen, sondern genau erkunden.
Da gerade Frühling ist, verwenden wir eine zufällige Teilmenge des berühmten iris-Datensatzes. Wenn wir die petal length gegen die petal width auftragen, die species auf die Farbe abbilden und ein wenig mit den aesthetics wie shape, color und size spielen, erhalten wir diesen frühlingshaften Plot:

<span class="hljs-comment"># Base plot</span>
plot_base <- ggplot(data = df_iris) +
geom_point(aes(x = Petal.Length, y = Petal.Width, color = Species),
size = <span class="hljs-number">3</span>, alpha = <span class="hljs-number">0.9</span>, shape = <span class="hljs-number">8</span>) +
geom_point(aes(x = Petal.Length, y = Petal.Width),
color = <span class="hljs-string">"yellow"</span>, size = <span class="hljs-number">0.4</span>) +
scale_color_manual(values = c(<span class="hljs-string">"#693FE9"</span>, <span class="hljs-string">"#A089F8"</span>, <span class="hljs-string">"#0000FF"</span>)) +
theme_minimal()
Kartesisches Koordinatensystem
Hinein- und Herauszoomen
Das Koordinatensystem kann manipuliert werden, indem man eines der verschiedenen Koordinatensysteme von ggplot hinzufügt. Wenn man sich ein Koordinatensystem vorstellt, denkt man höchstwahrscheinlich an ein kartesisches. Das Cartesian coordinate system kombiniert die x- und y-Dimension orthogonal und ist der Standard in ggplot (coord_cartesian
).
Es gibt zudem mehrere Varianten des bekannten kartesischen Koordinatensystems in ggplot, nämlich coord_fixed
, coord_flip
und coord_trans
. Für alle diese Varianten kann der dargestellte Abschnitt der Daten angegeben werden, indem man den maximal dargestellten Wert auf der x-Achse (xlim =
) und der y-Achse (ylim =
) definiert. Dies ermöglicht es, in einen Plot hinein oder herauszuzoomen.
Ein großer Vorteil besteht darin, dass alle Manipulationen des Koordinatensystems lediglich die Darstellung der Daten verändern – nicht aber die Daten selbst.
<span class="hljs-comment"># Zooming in with xlim/ylim</span>
plot_base +
coord_cartesian(xlim = 5, ylim = 2) +
ggtitle("coord_cartesian <span class="hljs-keyword">with</span> xlim = <span class="hljs-number">5</span> <span class="hljs-keyword">and</span> ylim = <span class="hljs-number">2</span><span class="hljs-string">")
</span>

Das „Seitenverhältnis“ der Achsen festlegen
Mit coord_fixed
kann man das genaue Verhältnis der Länge einer y-Einheit zur Länge einer x-Einheit in der endgültigen Visualisierung festlegen (aspect ratio).
# Setting the <span class="hljs-string">"aspect ratio"</span> of <span class="hljs-symbol">y</span> vs. <span class="hljs-symbol">x</span> units
plot_base +
coord_fixed(ratio = <span class="hljs-number">1</span>/<span class="hljs-number">2</span>) +
ggtitle(<span class="hljs-string">"coord_fixed with ratio = 1/2"</span>)

Transformation der Skalen der Achsen
Dies hilft dabei, genau die Erkenntnis hervorzuheben, die man vermitteln möchte. Eine weitere Möglichkeit dafür bietet coord_trans
, das verschiedene Transformationen der x- und y-Variablen erlaubt (siehe Tabelle unten, entnommen aus Wickham 2016, Seite 97).
Ich möchte das noch einmal betonen: Sehr praktisch ist, dass sich solche Transformationen nur auf die dargestellte Skala beziehen – nicht auf die tatsächlichen Daten.
Das ist auch der Grund, warum – unabhängig von der durchgeführten Transformation – die Originalwerte als Achsenbeschriftungen verwendet werden.
<span class="hljs-comment"># Transforming the axes </span>
<span class="hljs-attribute">plot_base</span> +
coord_trans(x = <span class="hljs-string">"log"</span>, y = <span class="hljs-string">"log2"</span>) +
ggtitle(<span class="hljs-string">"coord_trans with x = "log" and y = "log2""</span>)

Achsen vertauschen
Die letzte der kartesischen Optionen, coord_flip
, vertauscht die x- und y-Achse. Diese Option kann beispielsweise nützlich sein, wenn man die Ausrichtung von univariaten Plots wie Histogrammen oder Plot-Typen wie Boxplots ändern möchte – also solchen, die die Verteilung einer kontinuierlichen Variable über die Kategorien einer anderen Variable darstellen.
Nichtsdestotrotz funktioniert coord_flip
auch mit allen anderen Plots. Dadurch vervielfachen sich die gestalterischen Möglichkeiten für Plots – insbesondere, da sich alle kartesischen Koordinatensysteme miteinander kombinieren lassen.
<span class="hljs-comment"># Swapping axes </span>
<span class="hljs-comment"># base plot #2</span>
p1 <- ggplot(data = df_iris) +
geom_bar(aes(<span class="hljs-keyword">x</span> = Species, fill = Species), alpha = <span class="hljs-number">0</span>.<span class="hljs-number">6</span>) +
scale_fill_manual(<span class="hljs-keyword">values</span> = c(<span class="hljs-string">"#693FE9"</span>, <span class="hljs-string">"#A089F8"</span>, <span class="hljs-string">"#4f5fb7"</span>)) +
theme_minimal()
<span class="hljs-comment"># base plot & coord_flip()</span>
p2 <- ggplot(data = df_iris) +
geom_bar(aes(<span class="hljs-keyword">x</span> = Species, fill = Species), alpha = <span class="hljs-number">0</span>.<span class="hljs-number">6</span>) +
scale_fill_manual(<span class="hljs-keyword">values</span> = c(<span class="hljs-string">"#693FE9"</span>, <span class="hljs-string">"#A089F8"</span>, <span class="hljs-string">"#4f5fb7"</span>)) +
theme_minimal() +
coord_flip()
gridExtra::grid.arrange(p1, p2, top = <span class="hljs-string">"Bar plot without and with coord_flip"</span>)

Polares Koordinatensystem
Die Anpassung kartesischer Koordinatensysteme erlaubt eine feine Abstimmung von Plots. Doch coord_polar
, das letzte hier behandelte Koordinatensystem, verändert den gesamten Charakter eines Plots.
Durch die Verwendung von coord_polar
werden bar geoms in Kreisdiagramme (pie charts) oder „Zielscheiben“-Plots (bullseye plots) verwandelt, während line geoms in Radar-Charts umgewandelt werden.
Dies geschieht, indem x und y den Winkeln und Radien des resultierenden Plots zugewiesen werden. Standardmäßig wird die x-Variable dem Winkel zugeordnet, aber durch Setzen des Arguments theta
in coord_polar
auf "y"
kann dies geändert werden.


Auch wenn solche Plots in Bezug auf Neuheit und Optik glänzen mögen, sind ihre wahrnehmungspsychologischen Eigenschaften komplex, und ihre korrekte Interpretation kann ziemlich schwierig und eher unintuitiv sein.
<span class="hljs-meta"># Base plot 2 (long format, x = 1 is summed up to generate count)</span>
plot_base_2 <- df_iris %>%
dplyr::mutate(x = <span class="hljs-number">1</span>) %>%
ggplot(.) +
geom_bar(aes(x = x, fill = Species), alpha = <span class="hljs-number">0.6</span>) +
theme(axis.text = element_blank(),
axis.ticks = element_blank(),
axis.title = element_blank()) +
scale_fill_manual(values = c(<span class="hljs-string">"#693FE9"</span>, <span class="hljs-string">"#A089F8"</span>, <span class="hljs-string">"#4f5fb7"</span>)) +
theme_minimal() +
ggtitle(<span class="hljs-string">"base plot"</span>)
<span class="hljs-meta"># Bullseye plot </span>
<span class="hljs-meta"># geom_bar & coord_polar(theta = <span class="hljs-meta-string">"x"</span>)</span>
p2 <- plot_base_2 +
coord_polar(theta = <span class="hljs-string">"x"</span>) +
ggtitle(<span class="hljs-string">"theta = "x""</span>)
<span class="hljs-meta"># Pie chart </span>
<span class="hljs-meta"># geom_bar & coord_polar(theta = <span class="hljs-meta-string">"y"</span>)</span>
p3 <- plot_base_2 +
coord_polar(theta = <span class="hljs-string">"y"</span>) +
ggtitle(<span class="hljs-string">"theta = "y""</span>)
gridExtra::grid.arrange(p2, p3, plot_base_2, top = <span class="hljs-string">"geom_bar & coord_polar"</span>, ncol = <span class="hljs-number">2</span>)
# Base plot <span class="hljs-number">3</span> (long format, <span class="hljs-built_in">mean</span> width/length of sepals/petals calculated)
plot_base_3 <- iris %>%
dplyr::group_by(Species) %>%
dplyr::summarise(Petal.Length = <span class="hljs-built_in">mean</span>(Petal.Length),
Sepal.Length = <span class="hljs-built_in">mean</span>(Sepal.Length),
Sepal.Width = <span class="hljs-built_in">mean</span>(Sepal.Width),
Petal.Width = <span class="hljs-built_in">mean</span>(Petal.Width)) %>%
reshape2::melt() %>%
ggplot() +
geom_polygon(aes(group = Species, color = Species, <span class="hljs-symbol">y</span> = value, <span class="hljs-symbol">x</span> = variable),
fill = NA) +
scale_color_manual(values = c(<span class="hljs-string">"#693FE9"</span>, <span class="hljs-string">"#A089F8"</span>, <span class="hljs-string">"#4f5fb7"</span>)) +
theme_minimal() +
ggtitle(<span class="hljs-string">"base plot"</span>)
# Radar plot
# geom_polygon & coord_polar
p2 <- plot_base_3 +
theme_minimal() +
coord_polar() +
ggtitle(<span class="hljs-string">"coord_polar"</span>)
gridExtra::grid.arrange(plot_base_3, p2, top = <span class="hljs-string">"geom_polygon & coord_polar"</span>, ncol = <span class="hljs-number">2</span>)
Referenzen
- Wickham, H. (2016). ggplot2: elegant graphics for data analysis. Springer.