简体   繁体   中英

ggplot2 + ggrepel adding legend with label colours changes the colours itself

Assume the following data:

library(tidyverse)
library(ggrepel)
df <- data.frame(name   = rep(letters[1:3], 3),
                 points = c(5, 3, 7, 12, 13, 14, 20, 30, 40),
                 time = rep(c("day 1", "day 2", "day 3"), each = 3))

df2 <- df %>%
  group_by(name) %>%
  mutate(points_sum = cumsum(points)) %>%
  group_by(time) %>%
  mutate(rank = rank(desc(points_sum), ties.method = "min")) %>%
  ungroup() %>%
  mutate(name_colour = case_when(rank == 1 ~ "#336600",
                                 rank == 2 ~ "#339900",
                                 rank == 3 ~ "#66ff33"))

I now want to draw th following plot, ie give the names/labels the colour specified in the name_colour column:

df2 %>%
  ggplot(aes(x     = time,
             y     = points_sum,
             group = name,
             label = name)) +
  geom_point() +
  geom_text_repel(direction = "y", size = 10, colour = df2$name_colour) +
  theme_minimal()

没有传说的情节

However, this plot is missing a legend for these colours, ie I want to add a legend that has the ranks next to the according colour.

I'm not sure how I could manually add such a legend here. I tried to change my code above by the one below (only chenge in the second to last line), but this completely changes the colours of the labels:

df2 %>%
  ggplot(aes(x     = time,
             y     = points_sum,
             group = name,
             label = name)) +
  geom_point() +
  geom_text_repel(direction = "y", size = 10, aes(colour = name_colour)) +
  theme_minimal() 

用图例绘图,但颜色错误

Any ideas?

If you want to use the color codes from your dataframe then make use of scale_color_identity . By default this will not give you a legend so you have to add guide = guide_legend() :

library(tidyverse)
library(ggrepel)
df <- data.frame(
  name = rep(letters[1:3], 3),
  points = c(5, 3, 7, 12, 13, 14, 20, 30, 40),
  time = rep(c("day 1", "day 2", "day 3"), each = 3)
)

df2 <- df %>%
  group_by(name) %>%
  mutate(points_sum = cumsum(points)) %>%
  group_by(time) %>%
  mutate(rank = rank(desc(points_sum), ties.method = "min")) %>%
  ungroup() %>%
  mutate(name_colour = case_when(
    rank == 1 ~ "#336600",
    rank == 2 ~ "#339900",
    rank == 3 ~ "#66ff33"
  ))

df2 %>%
  ggplot(aes(
    x = time,
    y = points_sum,
    group = name,
    label = name
  )) +
  geom_point() +
  geom_text_repel(aes(color = name_colour), direction = "y", size = 10) +
  scale_color_identity(labels = c("A", "B", "C"), guide = guide_legend()) +
  theme_minimal()

In general, I think a more typical ggplot approach would be to specify the colours in scale_colour_manual or equivalent, rather than coding them into the data frame itself. For example:

library(ggplot2)
library(dplyr)
library(ggrepel)

data.frame(
        name   = rep(letters[1:3], 3),
        points = c(5, 3, 7, 12, 13, 14, 20, 30, 40),
        time = rep(c("day 1", "day 2", "day 3"), each = 3)
    ) %>%
    group_by(name) %>%
    mutate(points_sum = cumsum(points)) %>%
    group_by(time) %>%
    mutate(rank = factor(rank(desc(points_sum), ties.method = "min"))) %>%
    ungroup() %>%
    ggplot(aes(
            x     = time,
            y     = points_sum,
            group = name,
            label = name)) +
        geom_point() +
        geom_text_repel(direction = "y", size = 10, aes(colour = rank)) +
        theme_minimal() +
        scale_colour_manual(
            values = c("1" = "#336600", "2" = "#339900", "3" = "#66ff33")
        )

血小板

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