rggplot2

How can I move x-axis labels away from the centre of a ggplot that uses coord_polar?


I'm making a polar-transformed barplot in which several of the x-axis labels overlap with the plot area. For context, I'm working on a shiny application that you can find a copy of here (not any more).

I've tried using theme(axis.text.x = element_text(vjust = -someNumber)), but it doesn't seem to be doing anything.

Here is a reproducible example to demonstrate the problem:

## Tiny example plot
### Libraries
require(dplyr)
#> Loading required package: dplyr
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
require(ggplot2)
#> Loading required package: ggplot2

### Data
categories <- c("foo", "bar", "baz", "biff", "zoop", "sesquipedalian")
values <- c(100, 150, 42, 135.45, 177, 182)

plotThis <- tibble(names = categories, values = values)

### Plot the plot

ggplot(plotThis, aes(x = names, y = values)) + 
  geom_bar(stat = "identity", color = "black", fill = "blue", width = 1) + 
  coord_polar(clip = "off") +
  theme_minimal() +
  scale_y_continuous(name = NULL, breaks = NULL) +
  xlab(NULL)

Created on 2022-02-15 by the reprex package (v2.0.1)

How can I move the 'sesquipedalian' label (or, if necessary, all labels) further away from the centre so that it does not overlap with the plot?


Solution

  • This doesn't look nearly as nice as the answer from @Allan Cameron using his very slick {geomtextpath} library but has the (possible) advantage of being easy to implement with native {ggplot2}. Here we simply use expand_limits() in the y direction to push the axis further from the plot and leave room for the label. It's a bit of a hack because I came up with a fudge factor for how far to expand based on the length of the label and the size of that bar. It works OK with labels of a certain size but if they get really long it will break down a bit unless you introduce a line break. Also you can add theme(plot.margin = unit(c(3, 0, 3, 0), "lines")) to get more space around the plot to avoid cutting of super long labels.

    library(tidyverse)
    
    # data
    plotThis <- 
      tibble(
      names = c("foo", "bar", "baz", "biff", "zoop", "sesquipedalian"),
      values = c(100, 150, 42, 135.45, 177, 182))
    
    # calculate scaling of axis based on longest label
    new_max_y <- 
      plotThis %>% 
      mutate(nchar = nchar(names),
             new_max_y = values * (1 + 0.01 * nchar)) %>% 
      pull(new_max_y) %>% 
      max()
    
    # plot - expand margins if names get really long
    plotThis %>% 
      ggplot(aes(x = names, y = values)) +
      geom_col(color = "black", fill = "blue", width = 1) +
      coord_polar(clip = "off") +
      theme_minimal() +
      scale_y_continuous(name = NULL, breaks = NULL) +
      expand_limits(y = c(0, new_max_y)) +
      xlab(NULL)
    

    Created on 2022-02-15 by the reprex package (v2.0.1)