--- title: "Curved Text in Polar Co-ordinates" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Curved Text in Polar Co-ordinates} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7.16, fig.height = 6, dev = "ragg_png" ) ``` Polar co-ordinates in `ggplot2` allow the creation of a variety of circular plots. These include pie charts, donut plots, radar charts, and various circular versions of line, bar and scatter plots. In many circumstances, curved text that follows the polar co-ordinate system can be a clearer and more visually appealing way to label elements of these plots and their axes. However, this is not natively possible in `ggplot` due to the mechanism of text handling in the underlying `grid` graphics system. The `textpathGrob` at the heart of the `geomtextpath` package now makes it possible to create curved labels and axis text in polar co-ordinates with a minimum of effort. This vignette gives a brief demonstration of these features. We start by loading the necessary packages. ```{r setup} library(ggplot2) library(geomtextpath) ``` ## Curved axis labels This package includes a new `coord` called `coord_curvedpolar`, which is almost identical to `coord_polar`, but draws curved axis labels around the circumferential (theta) axis. The native `coord_polar` in `ggplot` produces horizontal axis labels, as we can show in the following example: ```{r weather_plot_coordpolar} df <- data.frame(Temperature = c(4.4, 4.6, 6.3, 8.7, 11.6, 14.1, 15.9, 15.5, 13.1, 9.7, 6.7, 4.3, 3.6, 3.9, 6.4, 9.7, 13.2, 15.8, 18, 17.8, 15.1, 11.2, 7.2, 4.4), City = rep(c("Glasgow", "Amsterdam"), each = 12), Month = factor(rep(month.name, 2), month.name)) p <- ggplot(df, aes(Month, Temperature)) + geom_col(aes(fill = City), position = position_dodge(width = 1)) + geom_vline(xintercept = 1:13 - 0.5, color = "gray90") + geom_hline(yintercept = 0:3 * 5, color = "gray90") + scale_fill_manual(values = c("darkorange", "dodgerblue4")) + ggtitle("Average monthly temperature in Amsterdam and Glasgow") + theme_bw() + theme(panel.border = element_blank(), axis.text.x = element_text(size = 14), axis.title.x = element_blank(), panel.grid.major = element_blank()) p + coord_polar() ``` Whereas, if we want curved axis labels, we can simply substitute `coord_curvedpolar` in as a replacement for `coord_polar` ```{r weather_plot_coordcurvedpolar} p + coord_curvedpolar() ``` The usual theme adjustments are available via `theme(axis.text.x = element_text())` ```{r weather_plot_coordcurvedpolar_theme} p + coord_curvedpolar() + theme(axis.text.x = element_text(face = 2, color = "orangered3", hjust = 0)) ``` Note that the text that would normally be upside down is automatically flipped to improve legibility. ## Curved labels It is also straightforward to create other labels that curve appropriately in polar co-ordinates, using `geom_textpath`. Straight text paths in Cartesian coordinates become curved in polar coordinates. ```{r coords_cartesian} df <- data.frame(x = c(1, 1000), y = 1, text = "This is a perfectly flat label") p <- ggplot(df, aes(x, y, label = text)) + geom_textpath(size = 6) + ylim(c(0.9, 1.1)) p ``` ```{r coords_polar} p + coord_polar(start = pi) ``` Similarly, the other geoms that are based on the same underlying mechanism curve in polar co-ordinates. For example, take the following plot in standard co-ordinates with a horizontal and vertical reference line: ```{r mtcars_reference} p <- ggplot(mtcars, aes(mpg, disp)) + geom_point() + geom_texthline(yintercept = 200, label = "displacement", hjust = 0, vjust = -0.2, color = "red4") + geom_textvline(xintercept = 20, label = "consumption", hjust = 0.8, linetype = 2, vjust = 1.3, color = "blue4") p ``` If we translate to polar co-ordinates, the reference lines transform, so that our horizontal line becomes a circle and our vertical line becomes a radial line. However, we don't need to change our labels; they will adhere to each path as it transforms without needing any other input from the user: ```{r mtcars_polar} p + coord_polar() ``` This means that with geomtextpath, you are free to design and label plots or diagrams in Cartesian co-ordinates: ```{r fancy_cartesian} df <- data.frame(x1 = c(seq(0, 10/6 * pi, pi/3), seq(0, 10/6 * pi, 2*pi/3)), y1 = c(rep(2, 6), rep(-1, 3)), x2 = c(seq(0, 10/6 * pi, pi/3) + pi/3, seq(0, 10/6 * pi, 2*pi/3) + 2*pi/3), y2 = c(rep(4, 6), rep(2, 3)), group = letters[c(1:6, (1:3) * 2)], alpha = c(rep(1, 6), rep(0.4, 3))) p <- ggplot(df, aes(x1, y1)) + geom_rect(aes(xmin = x1, xmax = x2, ymin = y1, ymax = y2, fill = group, alpha = alpha), color = "white", size = 2) + geom_textpath(data = data.frame(x1 = seq(0, 2 * pi, length = 300), y1 = rep(0.5, 300), label = rep(c("stats", "effects", "polar"), each = 100)), aes(label = label), linetype = 0, size = 8, upright = TRUE) + geom_textpath(data = data.frame(x1 = seq(0, 2 * pi, length = 300), y1 = rep(3, 300), label = rep(c("density", "smooth", "unique", "organic", "easy to use", "automatic"), each = 50)), aes(label = label), linetype = 0, size = 4.6, color = "white", upright = TRUE) + scale_y_continuous(limits = c(-5, 4)) + scale_x_continuous(limits = c(0, 2*pi)) + scale_fill_manual(values = c("deepskyblue3", "deepskyblue4", "green3", "green4","tomato", "tomato2")) + scale_alpha_identity() + theme_void() + theme(legend.position = "none") p ``` Which will flip nicely to polar co-ordinates without the need for re-labelling. ```{r fancy_polar} p + coord_polar() ```