Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot colour bar with 2 scales (top and bottom)

I am trying to make a ggplot2 with a colour bar with two scales (or two sets of labels) on both sides of the colour bar (for example having both a cm and inches scale on the left and right side of colour guide bar or having Celsius AND Fahrenheit). Is something like that possible in ggplot2? See picture for what I am looking for (ideally, in this small example I would have the numbers 1:5 at the bottom of the bar and the letters a:e on the top of the bar). Could I make two legends and just overlay them somehow? also having a title on the top and bottom would be helpful

df <- tibble(A = letters[1:5], B = 1:5)
  
ggplot(df, aes(x = A, y = B, fill = B)) +
  geom_col() +
  scale_fill_gradient(high = "blue",  low = "red",
                      labels = letters[1:5],
                       guide = guide_colorbar(
                         direction = "horizontal",
                         title.position = 'top',
                         title.hjust = 0.5,
                         label.hjust = 0.5,
                         legend.location = "bottom",
                         label.position = "top")
                      ) +
  theme(legend.position = "bottom")

enter image description here

like image 216
L Smeets Avatar asked Oct 22 '25 08:10

L Smeets


1 Answers

A more recent option to come close to achieve your desired result would be to use the legendry package. Unfortunately I wasn't able to find a solution to put the titles on the side.

library(ggplot2)
library(legendry)

df <- data.frame(A = letters[1:5], B = 1:5)

ggplot(df, aes(x = A, y = B, fill = B)) +
  geom_col() +
  scale_fill_gradient(
    high = "blue", low = "red",
    labels = letters[1:5]
  ) +
  theme(
    legend.position = "bottom",
    legend.text.position = "top"
  ) +
  guides(
    fill = guide_colbar(
      title = NULL,
      theme = theme(
        legend.title = element_text(
          hjust = .5, margin = margin()
        ),
        legend.text = element_text(
          margin = margin(t = 2, b = 2)
        )
      ),
      first_guide = compose_stack(
        primitive_ticks(),
        primitive_labels(),
        primitive_title(
          "A"
        ),
      ),
      second_guide = compose_stack(
        primitive_ticks(),
        primitive_labels(
          key = key_manual(
            aesthetic = 1:5
          )
        ),
        primitive_title(
          "B"
        )
      )
    )
  )

like image 195
stefan Avatar answered Oct 24 '25 22:10

stefan