The picture should give a good idea of what I would want to achieve. Ideally, the resulting colour bar would keep a continuous nature, i.e., should be based on a continuous rather than discrete aesthetic, or at least come very close to behave like it.
This also means, not just the simple approach of just bringing the legend keys of a discrete fill close enough together.
Yes, I could create a fake legend, but I'd like a solution that modifies at the legend drawing level.
I would be also very happy with interesting grid hacks!
library(ggplot2)
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"))
That's photoshopped, apologies!. I don't want to create the arrow, just the continuous scale with separators instead of ticks
The ultimate goal is to reproduce a color bar as orignially proposed in this thread
However, this is not about creating the discrete gradient bar, this is just about the separators!
The discrete gradient bar is not the problem, there are already solutions out there (e.g., https://stackoverflow.com/a/62544405/7941188, https://stackoverflow.com/a/62556763/7941188, https://stackoverflow.com/a/50540633/7941188)
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
}
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With