Plot data with conditional colors based on values in R

Viewed 129

I'm trying to make a bar plot (name vs. score) using ggplot2 with the following data:

name <- c("Jon", "Bill", "Maria", "Ben", "Tina")
A <- c(100, -100, -25, 45, 26)
B <- c(23, 100, -100, 48, 52)
C <- c(100, 29, 65, -100, 71)
D <- c(-100, 55, 39, 27, 100)
E <- c(100, -100, 59, 55, 52)
score <- c(27, 35, 42, 51, 66)
df <- data.frame(Name, A, B, C, D, E, score)

The graph can be generated using ggplot2

ggplot(df, aes(x = Name, y = score)) + geom_bar(stat = "identity")

However, I would like to fill the bar color based on the repetition of positive and negative values range, given in column A-E.

Basically, I would like to divide the bar height into two-part: the top half for positive values and the bottom half for negative values. The positive values need to be further grouped into custom ranges like 0-50 and 51-100 so 1/4th of bar height for 0-50 and another 1/4th for 51-100 (same true for negative values).

The stack color needs to be based on the frequency of the respective range (i.e. no. of sample with positive value in given range/total sample). Now suppose if all values fall between 51-100 range, the color should have darker shed (1 or maximum frequency) while if no value falls i.e. 0, then the color shed should be light. so finally each bar has four-part and each one is colored on the basis of repetition of the positive (0-50 & 51-100) and negative numbers (0- -50 & -51 - -100) frequency.

If there is any confusion, feel free to ask. Any help would be appreciated.

Thank you in advance.

1 Answers

You may do something like this-

library(tidyverse)

Name <- c("Jon", "Bill", "Maria", "Ben", "Tina")
A <- c(100, -100, -25, 45, 26)
B <- c(23, 100, -100, 48, 52)
C <- c(100, 29, 65, -100, 71)
D <- c(-100, 55, 39, 27, 100)
E <- c(100, -100, 59, 55, 52)
score <- c(27, 35, 42, 51, 66)
df <- data.frame(Name, A, B, C, D, E, score)

df %>%
  pivot_longer(!c(Name, score)) %>%
  mutate(dummy = cut(value, c(-100, -50, 0, 51, 100), include.lowest = T)) %>%
  count(Name, score, dummy) %>%
  complete(nesting(Name, score), dummy = levels(cut(-100:100, c(-100, -50, 0, 51, 100), include.lowest = T)), 
           fill = list(n = 0)) %>%
  mutate(dummy = factor(dummy, levels = rev(levels(cut(-100:100, c(-100, -50, 0, 51, 100), include.lowest = T))), 
                        ordered = TRUE)) %>%
  ggplot(aes(x = Name, y = score/4, fill = dummy, alpha = n, label = n)) +
  geom_bar(stat = 'identity') +
  geom_text(position = position_stack(vjust = 0.5)) +
  guides(alpha = 'none') +
  labs(fill = 'Partition',
       y = 'Score',
       subtitle = 'Values inside bar indicate Frequency') +
  geom_text(aes(x = Name, y = score, label = paste(Name, '-', score)), vjust = -0.5)

Created on 2021-08-22 by the reprex package (v2.0.0)

Related