Frank
Frank

Reputation: 1196

set diagonal elements to a certain color on geom_tile ggplot2

I want to produce a confusion matrix plot where the diagonal entries are green, the zero entries white, and the off-diagonal non-zero entries should be red.

This is the data:

gg <- structure(list(Prediction = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L, 10L), .Label = c("0", "1", "2", "3", "4", "5", "6", 
"7", "8", "9"), class = "factor"), Reference = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 
5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 
7L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 9L, 
9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 10L), .Label = c("0", "1", "2", "3", "4", 
"5", "6", "7", "8", "9"), class = "factor"), Freq = c(93L, 7L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 100L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 2L, 89L, 6L, 0L, 0L, 0L, 0L, 3L, 0L, 0L, 1L, 98L, 
0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 26L, 0L, 0L, 71L, 0L, 0L, 
3L, 0L, 0L, 2L, 69L, 0L, 0L, 1L, 25L, 0L, 3L, 0L, 0L, 6L, 64L, 
0L, 0L, 0L, 0L, 30L, 0L, 0L, 0L, 1L, 13L, 0L, 0L, 0L, 0L, 0L, 
86L, 0L, 0L, 3L, 96L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 4L, 37L, 
0L, 0L, 5L, 0L, 0L, 54L, 0L, 0L)), class = "data.frame", row.names = c(NA, 
-100L))

In this example, the off-diagonal zeros are white. But how can I intentionally set the diagonal to green and non-zero off-diagonal red?

gg %>% dplyr::mutate(Freq2 = ifelse(Freq == 0,NA,Freq)) %>% 
    ggplot(aes(Prediction, Reference, fill = Freq2)) +
    geom_tile() + 
    geom_text(aes(label=Freq)) +
    scale_fill_gradientn(colours = c("#f8766d", "#00ba38"),na.value="white") +
    labs(x = "Prediction",y = "Reference", fill = "Freq")

enter image description here

Upvotes: 2

Views: 674

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388982

One option using scale_fill_identity -

library(dplyr)
library(ggplot2)

gg %>% 
  mutate(color = case_when(Prediction == Reference ~ 'green', 
                           Freq == 0 ~ 'white', 
                           TRUE ~ ' red')) %>%
  ggplot(aes(Prediction, Reference, fill = color)) +
  geom_tile() + 
  geom_text(aes(label=Freq)) +
  scale_fill_identity() + 
  labs(x = "Prediction",y = "Reference")

enter image description here

Upvotes: 3

Frank
Frank

Reputation: 1196

Figured it out. Had to use scale_fill_manual

gg2 <- gg %>% dplyr::mutate(Freq2 = ifelse(Freq == 0,NA,Freq)) 
gg2[gg2$Prediction == gg2$Reference,]$Freq2 = "diag"
gg2[gg2$Prediction != gg2$Reference & !is.na(gg2$Freq2),]$Freq2 = "notDiag"
gg2 %>%
    ggplot(aes(Prediction, Reference, fill = Freq2)) +
    geom_tile() + 
    geom_text(aes(label=Freq)) +
    scale_fill_manual(values=c("#00ba38", "#f8766d"),na.value="white")+ 
    labs(x = "Prediction",y = "Reference", fill = "Freq")

enter image description here

Upvotes: 1

Related Questions