Home > OS >  Stacked barplot with colors depending on numbers and length of a vector
Stacked barplot with colors depending on numbers and length of a vector

Time:09-18

I have a dataframe that looks like this

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

I would like to create a stacked barplot in this fashion: enter image description here

So basically I map a certain value to a corresponding color (9 -> white (invisible), 0 -> green 2 -> red), and then create a bar of a length that is equal to the number of appearances of the value in a dataframe column. Is there any way to do something like this, i.e. using ggplot2?

CodePudding user response:

You could change your dataframe to a long format using pivot_longer. Add a column with the colors you want to show the bars using case_when for example. You could use scale_fill_identity to fill the bars to the corresponding color. To get the same order fill in your stacked bars as your dataframe, you could use ggplot_build to modify the data of your plot by replace the column of "fill" with a vector of the same order as your dataframe. You can use the following code:

library(ggplot2)
library(tidyr)
library(dplyr)
library(scales)
# Create plot
p <- df %>%
  mutate(index = 1) %>%
  pivot_longer(cols = -index) %>%
  mutate(color = case_when(value == 9 ~ 'white',
                           value == 0 ~ 'darkgreen',
                           TRUE ~ 'red')) %>%
  ggplot(aes(x = index, y = name, fill = color))  
  geom_col(width = 0.3)  
  scale_fill_identity()  
  theme_classic()  
  scale_x_continuous(expand = c(0,0), breaks = pretty_breaks(2))  
  labs(x = '', y = '')

# Extract vector of colors in right order
vec_colors <- df %>%
  mutate(index = 1) %>%
  pivot_longer(cols = -index) %>%
  mutate(color = case_when(value == 9 ~ 'white',
                           value == 0 ~ 'darkgreen',
                           TRUE ~ 'red')) %>%
  arrange(name) %>%
  pull(color)

# right order colors
vec_colors
#>  [1] "darkgreen" "darkgreen" "darkgreen" "darkgreen" "darkgreen" "red"      
#>  [7] "red"       "red"       "red"       "red"       "white"     "white"    
#> [13] "white"     "darkgreen" "darkgreen" "red"       "red"       "red"      
#> [19] "darkgreen" "darkgreen"

# use ggplot_build to modify data and replace fill column with vector
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 
plot(q)

Created on 2022-09-17 with enter image description here


Data:

df <- structure(list(V1 = c(0, 0, 0, 0, 0, 2, 2, 2, 2, 2), V2 = c(9, 
9, 9, 0, 0, 2, 2, 2, 0, 0)), class = "data.frame", row.names = c(NA, 
-10L))
  • Related