Reputation: 3237
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?
Upvotes: 3
Views: 1029
Reputation: 5214
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)
Upvotes: 1
Reputation: 173898
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))
Upvotes: 4