2

I have searched a lot for a solution to this problem, and only found this similar question where the solution for a similar problem is described but seems to be too complicated.

ggplot2 heatmaps: using different gradients for categories

I would like to know if there is another EASIER solution for a similar problem.

I have a simple dataframe:

,X,Likelihood,Impact
1,A,Almost Certain,Catastrophic
2,B,Likely,Major
3,C,Possible,Moderate
4,D,Likely,Minor
5,E,Rare,Incidental
6,F,Unlikely,Incidental
7,G,Unlikely,Incidental

From which I want to build a heatmap. This is straightforward using:

ggplot(df, aes(Impact, Likelihood)) + 
  geom_tile(aes(fill = X), colour = "white") + 
  geom_text(aes(label = X))

However, the color are distributed randomly, what I want to have is a custom color for each pair of (Impact, Likelihood). E.g., the tile for the pair (Almost Certain, Catastrophic) should be colored in 'red'.

How can I achieve this?

tonytonov
  • 25,060
  • 16
  • 82
  • 98
ifreak
  • 1,726
  • 4
  • 27
  • 45
  • The "Paired" palette from the RColorBrewer package is good for up to 12 colours (i.e. 6 pairs), if you want something quick. – Z.Lin Sep 14 '17 at 10:45

2 Answers2

3

You can create another column as the combination of likelihood and impact, and use named vector as the colors in scale_fill_manual For example,

df <- data.frame(X = LETTERS[1:3], 
                 Likelihood = c("Almost Certain","Likely","Possible"), 
                 Impact = c("Catastrophic", "Major","Moderate"), 
                 stringsAsFactors = FALSE)
df$color <- paste0(df$Likelihood,"-",df$Impact)

ggplot(df, aes(Impact, Likelihood)) + geom_tile(aes(fill = color),colour = "white") + geom_text(aes(label=X)) +
  scale_fill_manual(values = c("Almost Certain-Catastrophic" = "red","Likely-Major" = "yellow","Possible-Moderate" = "blue"))
shaojl7
  • 565
  • 4
  • 13
  • This solution seems to be reasonable, but what should I do when I have more combinations? – ifreak Sep 14 '17 at 09:22
  • if you would like control over the colors for the impact and likelihood, then you would still need to specify it individually. To save a bit of time typing out the different combinations, you can get the list of unique combinations `com <- unique(df$color);` selecting colors of the corresponding size `colors <- colorRampPalette(c("red", "green"))(length(com))`. and order `com` in the corresponding order (eg. from Almost Certain -Catastrophic to unlikely) to match your color codes, and then add in the names `names(colors) <- com`. And use `... scale_fill_manual(values = colors)` – shaojl7 Sep 15 '17 at 01:51
0

Just add the scale like so:

+ scale_fill_manual(
    values = c("red", "green", "#cbf442", "magenta", "white", "#523a56", "yellow"))

enter image description here

tonytonov
  • 25,060
  • 16
  • 82
  • 98
  • What if the order changes? and how can I include colors even if the values are not existing in the dataframe – ifreak Sep 14 '17 at 09:22
  • You can set key-value pairs, see another answer. But you'll need to define the whole dictionary of colours in advance and perform a lookup there. – tonytonov Sep 14 '17 at 09:34
  • how can i tell ggplot2 to fill the other tiles with colors (from the scale_fill_manual) even if no data is there in the dataframe? – ifreak Sep 14 '17 at 09:47
  • `scale_fill_manual` is smart enough to use only those that are present, e.g. try adding `"anything-else" = "grey"` and everything still works fine. – tonytonov Sep 14 '17 at 09:59
  • I tried adding all other combinations to the fill_scale_manual but I still only get the ones that are present. – ifreak Sep 14 '17 at 11:28
  • Sorry, it's difficult to understand what you're trying to achieve and what your current code is. It seems you're fine with the answer for the original question -- ask another one and put a link here. – tonytonov Sep 14 '17 at 11:53