Detecting programmatically whether axis labels overlap

Viewed 137

Is there a way to detect whether axis labels overlap in ggplot2 programmatically?

Suppose I create the following graph:

library(dplyr)
library(tibble)
library(ggplot2)

dt <- mtcars %>% rownames_to_column("name") %>% 
  dplyr::filter(cyl == 8)

ggplot(dt, aes(x = name, y = mpg)) + geom_point()

enter image description here

I want to programmatically detect whether x-axis labels are overlapping and apply the following first remedy:

ggplot(dt, aes(x = name, y = mpg)) + geom_point() +
  scale_x_discrete(guide = guide_axis(n.dodge = 2))

enter image description here

Here is the tricky part. Say the dimensions are different and first remedy also overlaps like this:

enter image description here

I want to apply a second remedy like this:

ggplot(dt, aes(x = name, y = mpg)) + geom_point() +
  theme(axis.text.x = element_text(angle=45, hjust = 1, vjust = 1)) 

enter image description here

Is it possible without visually inspecting the graph?

1 Answers

Not a definitive solution, but if we consider the margins constant, we can do some simple subtraction:

library(dplyr)
library(tibble)
library(ggplot2)

dt <- mtcars %>% rownames_to_column("name") %>% 
  dplyr::filter(cyl == 8)

p <- ggplot(dt, aes(x = name, y = mpg)) +
  geom_point()


# variable part
font_size <- 9 #points, the ggplot default
full_width <- 15 #cm
full_height <- 10 #cm

cm_to_pt <- 28.35 # 1 cm = 28.35 points

# try varying width
for(full_width in c(30, 40, 45, 50)){
  axis_text_length_pt <- ceiling(max(nchar(dt$name))/2)*font_size
  axis_available_pt <- full_width/n_distinct(dt$name)*cm_to_pt
  do_not_touch <- axis_text_length_pt <= axis_available_pt
  
  p +
    theme(axis.text.x = element_text(size=font_size)) +
    geom_text(aes(x=5,y=15, label=do_not_touch))
  ggsave(paste0("tmp_",full_width,".png"),
         width = full_width, height = full_height, unit = "cm")
}

At 40 cm we still have the Hornet Sportabout and the Lincoln Continental touching, at 45 cm they separate.

Related