How to automatically choose a good ylim to read geom_labels in ggplot2 in R

Viewed 97

Suppose I write the following code with the diamonds dataset:

library(tidyverse)

diamonds %>% 
    group_by(cut) %>% 
    summarize(total_value = sum(price, na.rm = TRUE)) %>% 
    arrange(total_value) %>% 
    mutate(cut = as_factor(cut)) %>% 
    mutate(across(where(is.numeric), ~round(., 1))) %>% 
    ggplot(aes(x = cut, y = total_value)) +
    geom_col(aes(fill = cut)) +
    theme(legend.position = "note") +
    coord_flip() +
    geom_label(aes(label = paste0("$", total_value)), size = 6) +
    labs(title = "Total Value of Diamonds by Cut", y = "USD", x = "") +
    theme(axis.text = element_text(size = rel(1)))

which outputs the following plot:

enter image description here

As you can see, it is impossible to read the last digit(s) of the first category ("Ideal").

So, my question is, I know I can simply write something like coord_flip(ylim = c(0,80000000) and this would solve the problem; however, what could I write instead for ggplot2 to automatically know by itself how much space it should provide in ylim for people to clearly read the geom_label()s without me having to do this manually?

I'm trying to create an automatic Dashboard with multiple plots such as this, but I cannot manually tune every one of those, I need an automatic mechanism and I haven't found anything regarding this on StackOverflow for geom_label() specifically.

Thanks.

1 Answers

Instead of positioning your label at the the bar, you could move it closer to the middle and adjust position with vjust so it won't spill out of the plot set to include the bars.

library(tidyverse)

diamonds %>% 
  group_by(cut) %>% 
  summarize(total_value = sum(price, na.rm = TRUE)) %>% 
  arrange(total_value) %>% 
  mutate(cut = as_factor(cut)) %>% 
  mutate(across(where(is.numeric), ~round(., 1))) %>% 
  ggplot(aes(x = cut, y = total_value)) +
  geom_col(aes(fill = cut)) +
  theme(legend.position = "note") +
  coord_flip() +
  geom_label(aes(label = paste0("$", total_value), y = total_value/2), size = 6, hjust = 0.2) +
  labs(title = "Total Value of Diamonds by Cut", y = "USD", x = "") +
  theme(axis.text = element_text(size = rel(1)))

That gives:

plot without clipped labels

Related