Home > Software engineering >  Fix axis label length in ggplot2
Fix axis label length in ggplot2

Time:02-17

library(tidyverse)
df <- data.frame(x = c(1, 2, 3, 4), 
                 y1 = c(1, 3, 2, 4), 
                 y2 = c(3000, 2000, 4000, 1000))
label_1 = c("1", "2", "3") %>% format(width = 5, justify = "right")
label_2 = c("1000", "2000", "3000") %>% format(width = 5, justify = "right")
p1 <- df %>% ggplot(aes(x = x, y = y1)) 
  geom_line() 
  scale_y_continuous(breaks = c(1, 2, 3), 
                     labels = label_1)
p2 <- df %>% ggplot(aes(x = x, y = y2)) 
  geom_line() 
  scale_y_continuous(breaks = c(1000, 2000, 3000), 
                     labels = label_2)
p1
p2

enter image description here enter image description here

In the above code, I try to make p1 and p2 to have the same length of y-axis label, by format(width = 5). In the actual graph, labels in p1 are still shorter than those in p2.

By trial and error, I get the right length when setting width =8.

label_3 = c("1", "2", "3") %>% format(width = 8, justify = "right")
p1 <- df %>% ggplot(aes(x = x, y = y1)) 
  geom_line() 
  scale_y_continuous(breaks = c(1, 2, 3), 
                     labels = label_3)
p1

enter image description here

Could someone please explain this or guide me to the relevant previous posts?

CodePudding user response:

The regular space does not have the same width as a digits (in non-monospaced fonts). Unicode has a 'figure space' that has 'tabular width', i.e. the same width as digits. If you make a helper function that replaces spaces with the tabular widths (\u2007), both plots should have the same size for their y-axis. The function:

pad_numbers <- function(x, width, justify = "right") {
  x <- format(x, width = width, justify = justify)
  gsub(" ", "\u2007", x)
}

In action:

library(tidyverse)
df <- data.frame(x = c(1, 2, 3, 4), 
                 y1 = c(1, 3, 2, 4), 
                 y2 = c(3000, 2000, 4000, 1000))

label_1 = c("1", "2", "3") %>% pad_numbers(width = 5, justify = "right")
label_2 = c("1000", "2000", "3000") %>% pad_numbers(width = 5, justify = "right")
p1 <- df %>% ggplot(aes(x = x, y = y1)) 
  geom_line() 
  scale_y_continuous(breaks = c(1, 2, 3), 
                     labels = label_1)
p2 <- df %>% ggplot(aes(x = x, y = y2)) 
  geom_line() 
  scale_y_continuous(breaks = c(1000, 2000, 3000), 
                     labels = label_2)

p1

p2

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

Lastly, if you want the y-axis to have the same width for plot composition purposes, I recommend the {ragg} package, which does a good job at aligning the panels between two plots. This wouldn't require the helper function we wrote at the beginning.

  • Related