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:
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)
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))