3

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.

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?

Captain Hat
  • 2,444
  • 1
  • 14
  • 31
  • https://stackoverflow.com/questions/36916773/how-to-move-x-axis-labels-using-coord-polar-in-ggplot2 is a related question from 2016, but asking how to stop the labels from being cropped by the margins of the plot. The accepted answer to that question has been made obsolete by the addition of the convenient 'clip' argument to `coord_polar` – Captain Hat Feb 15 '22 at 11:55

2 Answers2

4

If you switch from coord_polar to coord_curvedpolar from the geomtextpath package, you can have curved labels that never overlap the plotting area. The problem you describe was the main reason for writing coord_curvedpolar in the first place.

In addition, the x axis labels are adjustable in the radial direction using the vjust setting inside theme(axis.text.x = element_text(...)).

No other parts of your code need to change, and the other elements of the plot are exactly the same as they would be with coord_polar.

I think this makes for a much nicer looking plot (though I am possibly biased...)

library(geomtextpath)

ggplot(plotThis, aes(x = names, y = values)) + 
  geom_bar(stat = "identity", color = "black", fill = "blue", width = 1) + 
  coord_curvedpolar(clip = "off") +
  theme_minimal() +
  scale_y_continuous(name = NULL, breaks = NULL) +
  xlab(NULL) +
  theme(axis.text.x = element_text(vjust = -1, size = 15))

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
1

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)

Dan Adams
  • 4,971
  • 9
  • 28