Home > Net >  Bar chart with colours that correspond to values
Bar chart with colours that correspond to values

Time:09-27

There's a given dataframe

df <- data.frame("V1" = c(0,0,0,0,0,2,2,2,2,2,3,3,3),
                 "V2" = c(9,9,9,0,0,2,2,2,0,0,3,0,0))

and I would like to create a bar plot out of it, where each value has a specific colour. With the great help of one of users we managed to create code

p <- df %>%
  mutate(index = 1) %>%
  pivot_longer(cols = -index) %>%
  mutate(color = case_when(value == 9 ~ 'white',
                           value == 0 ~ 'darkgreen',
                           value == 1 ~ 'blue',
                           value == 2 ~ 'red',
                           value == 3 ~ 'darkorange')) %>%
  ggplot(aes(x = index, y = name, fill = color))  
  geom_col(width = 0.3)  
  scale_fill_identity(guide = 'legend')  
  theme_classic()  
  scale_x_continuous(expand = c(0,0), breaks = pretty_breaks(2))

vec_colors <- df %>%
  mutate(index = 1) %>%
  pivot_longer(cols = -index) %>%
  mutate(color = case_when(value == 9 ~ 'white',
                           value == 0 ~ 'darkgreen',
                           value == 1 ~ 'blue',
                           value == 2 ~ 'red',
                           value == 3 ~ 'darkorange')) %>%
  arrange(name) %>%
  pull(color)

q <- ggplot_build(p)
q$data[[1]] <- q$data[[1]] %>%
  group_by(y) %>%
  arrange(x, .by_group = TRUE) 

q$data[[1]]$fill <- vec_colors

q <- ggplot_gtable(q)
plot(q)

that results in such a plot enter image description here

Question: how do I create a legend that looks like this?

enter image description here

Or like this?

enter image description here

CodePudding user response:

Well, first your approach to achieve your desired result is quite complicated. Instead you could simplify using a named color vector and switching to scale_fill_manual. Doing so will give you atomatically a legend similar to your desired result which I tweak a bit using the breaks argument. Also, instead of geom_col I would go for geom_tile. To this end use the row number as the index.

library(dplyr)
library(tidyr)
library(ggplot2)

df_long <- df %>%
  mutate(index = row_number()) %>%
  pivot_longer(cols = -index)

cols <- c( 'white', 'darkgreen', 'blue', 'red', 'darkorange')
names(cols) <- c(9, 0, 1, 2, 3)

ggplot(df_long, aes(x = index, y = name, fill = factor(value)))  
  geom_tile(height = .3)  
  scale_fill_manual(values = cols, limits = force, breaks = c(0, 3, 2), name = "State")  
  theme_classic()  
  scale_x_continuous(expand = c(0,0), breaks = scales::pretty_breaks(2))

  • Related