简体   繁体   中英

Color legend key labels with R ggplot2 and remove the keys

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM