How could one color the legend key labels with R ggplot2
and hide the keys themselves?
library(ggplot2)
ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) +
geom_point()
In a way that the legend contains only the text labels 4
, 6
and 8
colored in red, green and blue respectively.
There's no way to do this directly using theme
, since element_text
won't take vectorized input. Probably easiest to fake it by turning clipping off and plotting some text where the legend should be:
library(ggplot2)
ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) +
geom_point() +
geom_text(data = data.frame(wt = c(6, 6, 6, 6), mpg = c(20, 22.5, 25, 27.5),
cyl = c(levels(factor(mtcars$cyl)), "cyl"),
colour = c(levels(factor(mtcars$cyl)), "cyl")),
aes(label = colour)) +
coord_cartesian(xlim = c(1.5, 5.5), clip = "off") +
scale_color_manual(values = c("blue", "green", "red", "black")) +
theme(legend.position = "none",
plot.margin = margin(10, 50, 10, 10))
Allan's answer is also excellent, but here is a more automated way of doing it by making your own custom guide function.
library(ggplot2)
guide_textcolourguide <- function(...) {
guide <- guide_legend(...)
class(guide) <- c("guide", "textcolourguide", "legend")
guide
}
guide_gengrob.textcolourguide <- function(guide, theme) {
legend <- NextMethod()
# Figure out what are keys and labels
keys <- grep("^key(?!.*bg)", legend$layout$name, perl = TRUE)
labels <- grep("^label", legend$layout$name)
# Recolour the labels based on keys, assumes parallel ordering
newlabels <- mapply(function(key, lab) {
colour <- legend$grobs[[key]]$gp$col
lab <- legend$grobs[[lab]]
lab$children[[1]]$children[[1]]$gp$col <- colour
return(lab)
}, key = keys, lab = labels, SIMPLIFY = FALSE)
# Replace labels
legend$grobs[labels] <- newlabels
# Purge keys
gtable::gtable_filter(legend, "key", invert = TRUE)
}
ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) +
geom_point() +
scale_colour_discrete(guide = "textcolourguide")
Created on 2020-08-13 by the reprex package (v0.3.0)
You could also use ggtext
, by renaming the cyl
variable and using element_markdown
for the legend. There might be more elegant ways to make sure the factor levels match... but it is a way to programmatically provide the colors to the legend.
library(ggplot2)
library(dplyr)
library(ggtext)
setColors <- function(x, col="red")
paste0("<span style = 'color:", col, ";'>", x, "</span>")
mycols <- setNames(colorspace::rainbow_hcl(length(unique(mtcars$cyl))),
unique(sort(mtcars$cyl)))
mtcars %>%
mutate(cyl = factor(setColors(cyl, col= mycols[as.character(cyl)]),
unique(setColors(cyl, col = mycols[as.character(cyl)]))[
order(unique(cyl))])) %>%
ggplot(aes(wt, mpg, colour = cyl)) +
geom_point() +
theme(legend.text = element_markdown()) +
scale_color_manual(values = unname(mycols))
Created on 2020-08-13 by the reprex package (v0.3.0)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.