1

Thank you for looking at my question. I have created a heat map with a color gradient. The color gradient looks good, however, I would prefer that the colors be more defined. The first picture that I have attached here

Heatmap

is what I get when I run my code. The second picture

Desired Heatmap is what I would like to get. I am not sure how to solve this problem. A small sample of my code is below. To be clear, I would like for my code to return the second picture where the colors distinctly go from green, gold, orange, light red, red, and dark red.

library(RColorBrewer)
library(dplyr)
library(ggplot2)

nRow <- 5 
nCol <- 5 
m3 <- matrix(c(2,2,3,3,3,1,2,2,3,3,1,1,2,2,3,1,1,2,2,2,1,1,1,1,2), nrow = 5, ncol = 5, byrow = TRUE)
myData <- m3 #matrix(rnorm(nRow * nCol), ncol = nCol)
rownames(myData) <- c("5", "4", "3", "2","1")  
colnames(myData) <- c("1", "2", "3", "4","5")  
longData <- reshape2::melt(myData)
colnames(longData) <- c("Likelihood", "Consequence", "value")
longData <- mutate(longData, value = Consequence * Likelihood)

cols <-function(n) {
  colorRampPalette(rev(c("red4","red2","tomato2","orange","gold1","forestgreen")))(6)                                
}

display_risk <-  mutate(longData, value = Consequence * Likelihood)

ggplot(longData,aes(x = Consequence, y = Likelihood, fill = value))  +
  geom_tile() +
  scale_fill_gradientn(colours = cols(6)) +
  theme(axis.text.y = element_text(angle=90, hjust=1), legend.position = "none") +
  scale_x_continuous(name = "Probability", breaks = seq(1,5,1), expand = c(0, 0)) +
  scale_y_reverse(name= "Severity", breaks = seq(1,5,1), expand = c(0, 0)) +
  geom_hline(yintercept = seq(1.5,5.5)) +
  geom_vline(xintercept = seq(1.5,5.5)) +
  coord_fixed()

Here are some links to a few answers that I tried with no luck.

tjebo
  • 21,977
  • 7
  • 58
  • 94
J L
  • 15
  • 6
  • Welcome to SO. Thanks for providing an *almost* reproducible example (a "risk_data" object has sneaked its way into the code. I'll edit the code now - please check how I change the plot code. And remove the unnecessary library calls – tjebo Jan 22 '21 at 20:38
  • Thanks for your feedback! I appreciate it. – J L Jan 23 '21 at 05:24

1 Answers1

1

I can hardly think of a different way than to map your desired colors to specific value ranges. See below. Please check how I reduced your code, there were lots of unnecessary calls, (I guess you've copied it from a script where you have tried different stuff). Also, I have changed the colorRampPalette call - this is a function generator, no need to use function() here.

Notice you would need to manually define the values, and I guess this would be your researcher decision how to present the data. You need to scale it to a range 0:1

library(RColorBrewer)
library(dplyr)
library(ggplot2)

myData <- matrix(c(2,2,3,3,3,1,2,2,3,3,1,1,2,2,3,1,1,2,2,2,1,1,1,1,2), nrow = 5, ncol = 5, byrow = TRUE)
longData <- reshape2::melt(myData)
colnames(longData) <- c("Likelihood", "Consequence", "value")
longData <- mutate(longData, value = Consequence * Likelihood)
mycols <- rev(c("red4","red2","tomato2","orange","gold1","forestgreen"))
cols <- colorRampPalette(mycols)

myvals <- c(0, 8, 9, 10, 11, 25)
scaled_val <- scales::rescale(myvals, 0:1)

ggplot(longData, aes(x = Consequence, y = Likelihood, fill = value)) +
  geom_tile() +
  scale_fill_gradientn(colours = cols(length(mycols)), 
                       values = scaled_val) +
  theme(axis.text.y = element_text(angle = 90, hjust = 1), legend.position = "none") +
  scale_x_continuous(name = "Probability", breaks = seq(1, 5, 1), expand = c(0, 0)) +
  scale_y_reverse(name = "Severity", breaks = seq(1, 5, 1), expand = c(0, 0)) +
  geom_hline(yintercept = seq(1.5, 5.5)) +
  geom_vline(xintercept = seq(1.5, 5.5)) +
  coord_fixed()

Additionally you can define from where your gradient shall start. I've shown how to do this I a very recent thread. Note your desired output does not match the values (I've superimposed them to demonstrate that). Also notice this all is obviously all defined by yourself - those values that I chose are random, and it's up to you to tweak it to your liking.


myvals <- c(0, 6, 7, 9, 10, 11, 25)
scaled_val <- scales::rescale(myvals, 0:1)

ggplot(longData, aes(x = Consequence, y = Likelihood, fill = value)) +
  geom_tile() +
  geom_text(aes(label = value)) +
  scale_fill_gradientn(colours = c(mycols[1], mycols), 
                       values = scaled_val) +
  theme(axis.text.y = element_text(angle = 90, hjust = 1), legend.position = "none") +
  scale_x_continuous(name = "Probability", breaks = seq(1, 5, 1), expand = c(0, 0)) +
  scale_y_reverse(name = "Severity", breaks = seq(1, 5, 1), expand = c(0, 0)) +
  geom_hline(yintercept = seq(1.5, 5.5)) +
  geom_vline(xintercept = seq(1.5, 5.5)) +
  coord_fixed()

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • (I did not exaggerate too much with the gradient - you can play around with the values) – tjebo Jan 22 '21 at 21:18
  • Thank you! The colors are still not exactly how I would like them but they are better than what I had before. – J L Jan 23 '21 at 05:26
  • @JL see added graph. To tweak the values is entirely up to you. Your desired output does not match the given values. If you want perfect representation of your desired output, provide better sample data. – tjebo Jan 23 '21 at 12:19
  • 1
    thank you. I understand what you are saying. I was able to tweak the values to get the desired representation. Thank you so much for your help! – J L Jan 24 '21 at 13:34