Continuous color bar with separators instead of ticks

There's certainly a quick grid hack Tjebo, but it probably needs a bit of work to make it robust (indexing by name rather than by number):

library(ggplot2)
library(grid)

p <- ggplot(iris, aes(Sepal.Length, y = Sepal.Width, fill = Petal.Length))+
  geom_point(shape = 21) +
  scale_fill_continuous() +
  guides(fill = guide_colorbar(ticks.colour = "black"))

gt <- ggplot_gtable(ggplot_build(p))

x1 <- gt$grobs[[which(gt$layout$name == "guide-box")]]$grobs[[1]]$grobs[[5]]$x1
x1[1:7] <- x1[8:14]
gt$grobs[[which(gt$layout$name == "guide-box")]]$grobs[[1]]$grobs[[5]]$x1 <- x1
grid.newpage()
grid.draw(gt)

Created on 2020-06-24 by the reprex package (v0.3.0)


There definitely is an option with the extendable guide system introduced in ggplot v3.3.0. See example below:

library(ggplot2)

guide_longticks <- function(...) {
  guide <- guide_colorbar(...)
  class(guide) <- c("guide", "guide_longticks", "colorbar")
  guide
}

guide_gengrob.guide_longticks <- function(guide, theme) {
  dir <- guide$direction
  guide <- NextMethod()
  is_ticks <- grep("^ticks$", guide$layout$name)
  ticks <- guide$grobs[is_ticks][[1]]
  if (dir == "vertical") {
    ticks$x1 <- rep(tail(ticks$x1, 1), length(ticks$x1))
  } else {
    ticks$y1 <- rep(tail(ticks$y1, 1), length(ticks$y1))
  }
  
  guide$grobs[[is_ticks]] <- ticks
  guide
}

ggplot(iris, aes(Sepal.Length, y = Sepal.Width, fill = Petal.Length))+
  geom_point(shape = 21) +
  scale_fill_continuous() +
  guides(fill = guide_longticks(ticks = TRUE, ticks.colour = "black"))

Created on 2020-06-24 by the reprex package (v0.3.0)

EDIT:

Also try this alternative constructor if you want flat colours in between ticks:

guide_longticks <- function(...) {
  guide <- guide_colorsteps(...)
  class(guide) <- c("guide", "guide_longticks", "colorsteps", "colorbar")
  guide
}

EDIT2:

The following gengrob function would also delete the smaller ticks, if you want cleaner vector files. It kind of assumes that they are the last half of the ticks though:

guide_gengrob.guide_longticks <- function(guide, theme) {
  dir <- guide$direction
  guide <- NextMethod()
  is_ticks <- grep("^ticks$", guide$layout$name)
  ticks <- guide$grobs[is_ticks][[1]]
  n <- length(ticks$x0)
  if (dir == "vertical") {
    ticks$x0 <- head(ticks$x0, n/2)
    ticks$x1 <- rep(tail(ticks$x1, 1), n/2)
  } else {
    ticks$y0 <- head(ticks$y0, n/2)
    ticks$y1 <- rep(tail(ticks$y1, 1), n/2)
  }
  
  guide$grobs[[is_ticks]] <- ticks
  guide
}

Tags:

R

Legend

Ggplot2