Dat Vuong
Dat Vuong

Reputation: 27

Change `ggplot` label color by conditions

I have a question about changing color for geom_text & geom_label base on a condition.

Expected out put

Data

data <-  tibble(Factor = c("A", "B", "A", "B"),
   Score = c(90, 85, 85, 90),
   Year = c("2020", "2020", "2021", "2021"))

Data transform

   df_2 = data %>% 
     pivot_wider(names_from = Year, names_prefix = "Year", values_from = Score) %>% 
     mutate(gap = Year2021 - Year2020) %>% 
     select(Factor, gap)

Plot

data %>% 
  left_join(df_2) %>% 
  ggplot(aes(x = Factor, y = Score, fill = Year)) +
  geom_col(position='dodge') +
  geom_text(aes(label=Score), 
            position=position_dodge(width = 0.9), 
            vjust=-0.40) +
  geom_label(aes(y = 100, label = ifelse(Year == 2021, gap, NA_character_)), na.rm = TRUE) +
  scale_y_continuous(limits = c(0,105))
  theme_minimal()

enter image description here

Expected out put

Upvotes: 1

Views: 1754

Answers (2)

stefan
stefan

Reputation: 124138

Second option would be to use a manual scale for the text and bar colors. For the labels we could use the ggnewscale package which allows for multiple scales for the same aesthetic. Doing so we could add a second fill scale:

library(ggplot2)
library(ggnewscale)

ggplot(dat, aes(x = Factor, y = Score, fill = Year)) +
  geom_col(position = "dodge") +
  geom_text(aes(label = Score, color = Year),
    position = position_dodge(width = 0.9),
    vjust = -0.40
  ) +
  scale_color_manual(aesthetics = c("fill", "color"), values = c("2021" = "blue", "2020" = "grey")) +
  ggnewscale::new_scale_fill() +
  geom_label(aes(y = 100, label = ifelse(Year == 2021, gap, NA_character_), fill = gap > 0), na.rm = TRUE) +
  scale_fill_manual(values = c("FALSE" = "red", "TRUE" = "green")) +
  scale_y_continuous(limits = c(0, 105)) +
  theme_minimal()

enter image description here

DATA

data <- data.frame(
  Factor = c("A", "B", "A", "B"),
  Score = c(90, 85, 85, 90),
  Year = c("2020", "2020", "2021", "2021")
)

library(dplyr)
library(tidyr)

df_2 <- data %>%
  pivot_wider(names_from = Year, names_prefix = "Year", values_from = Score) %>%
  mutate(gap = Year2021 - Year2020) %>%
  select(Factor, gap)

dat <- data %>%
  left_join(df_2)

Upvotes: 2

Quinten
Quinten

Reputation: 41285

You can conditionally assign the colors to the aesthetics using case_when. You can use the following code:

library(tibble)
library(ggplot2)
library(dplyr)
library(tidyr)
data <-  tibble(Factor = c("A", "B", "A", "B"),
                Score = c(90, 85, 85, 90),
                Year = c("2020", "2020", "2021", "2021"))

df_2 = data %>% 
  pivot_wider(names_from = Year, names_prefix = "Year", values_from = Score) %>% 
  mutate(gap = Year2021 - Year2020) %>% 
  select(Factor, gap)

df <- data %>% left_join(df_2)
#> Joining, by = "Factor"
ggplot(df, mapping = aes(x = Factor, y = Score, fill = Year)) +
  geom_col(position='dodge') +
  geom_text(df, mapping = aes(label=Score, color = Year),
            color = case_when(
              df$Score == 85 & df$Year == 2021 | df$Score == 90 & df$Year == 2021 ~ "blue",
              df$Score == 85 & df$Year == 2020 | df$Score == 90 & df$Year == 2020 ~ "grey",
            ),
            position=position_dodge(width = 0.9), 
            vjust=-0.40) +
  geom_label(data = df, mapping = aes(y = 100, label = ifelse(Year == 2021, gap, NA_character_)),
             fill = case_when(
               df$gap == -5 ~ "red",
               df$gap == 5 ~ "green"
             ), na.rm = TRUE) +
  scale_y_continuous(limits = c(0,105)) +
  theme_minimal()

Created on 2022-09-24 with reprex v2.0.2

Upvotes: 2

Related Questions