How to add customized coding to ggplot2 Heat map

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
Apartment_no <- c("1-SV","1-SV","1-SV","1-SH","1-SH","1-SH","1-1V","1-1V","1-1V","1-1H","1-1H","1-1H","3-SV","3-SV","3-SV","3-1V","3-1V","3-1V","3-1H","3-1H","3-1H")
month <- c("September","October","November","September","October","November","September","October","November","September","October","November","September","October","November","September","October","November","September","October","November")
Days <- c(NA,19,28,2,19,28,2,19,NA,2,19,28,25,31,28,12,NA,24,8,26,19)
Heat_clean <- data.frame(Apartment_no,month,Days)

I have the above data, it's actually a sample data, in actual I have around 163 apartments and the data for all the 12 months. So I have plotted an interactive heat and I also want to add my personalized color coding to it, so I have used the following code:

mypalette=rep("Green",length(Days))
mypalette[Days <= 25] = "Pink"
mypalette[Days <= 15] = "Orange"
mypalette[Days <= 5] = "Blue"
mypalette[is.na(Days)] = "Red"

& then I have added it to my plotly code using the undermentioned code

p <- ggplot(Heat_clean,aes(month,as.factor(Apartment_no),fill=Days))+geom_tile(aes(fill=Days),color="white")+scale_fill_manual(values = mypalette)
plotly::ggplotly(p)

But for some reason it's giving me an error and the desired plot is not obtained.

You should include the error message in your post.

I ran the code, and the error I get is:
Error: Continuous value supplied to discrete scale
Is that the same error you are getting?

The error means you passed a numeric value where a discrete value (ie. factor) was expected.

A quick look at your input data reveals the culprit:

> str(Heat_clean)
'data.frame':	21 obs. of  3 variables:
 $ Apartment_no: Factor w/ 7 levels "1-1H","1-1V",..: 4 4 4 3 3 3 2 2 2 1 ...
 $ month       : Factor w/ 3 levels "November","October",..: 3 2 1 3 2 1 3 2 1 3 ...
 $ Days        : num  NA 19 28 2 19 28 2 19 NA 2 ...

Days is numeric. But scale_fill_manual() only applies to discrete values like strings and factors. For continuous/numeric values you must use scale_fill_gradient() or similar.

Solution:
fill=as.factor(Days). You can do this because sensible values for Days are only integers within a bounded range.
And you only need one fill aesthetic. Either the global one in ggplot(), or the local one in geom_tile().

Thanks @cymon, I used the following code now:

p <- ggplot(Heat_clean,aes(month,Apartment_no,fill=as.factor(Days)))+geom_tile()+scale_fill_manual(values = mypalette)

& I am getting the follwing error now
"Insufficient values in manual scale. 31 needed but only 21 provided"

That means your factor has more different levels than your palette has colours. You need one colour for each level of the factor. Either drop unused levels from the factor or add 10 more colours to the palette.

@cymon I have added some more colors but it's still giving the same error "Insufficient values in manual scale. 31 needed but only 21 provided". I believe the problem lies somewhere else.
Moreover, I don't want to add so many colors as it would make it more confusing. Furthermore, I have removed all the NA's from my data, now I just have numbers left.

This is happening because you are mapping the fill aesthetic to the Days variable which is continuous ranging from 1 to 31, that is why when you convert it to a factor it has 31 levels.
You cant map a discrete scale to a continuous variable, so you would have to bin your variable first in order to map a discrete variable to a discrete scale, like in this example

library(tidyverse)
Heat_clean <- data.frame(
          Days = c(NA, 19, 28, 2, 19, 28, 2, 19, NA, 2, 19, 28, 25, 31, 28,
                   12, NA, 24, 8, 26, 19),
  Apartment_no = as.factor(c("1-SV", "1-SV", "1-SV", "1-SH", "1-SH", "1-SH",
                             "1-1V", "1-1V", "1-1V", "1-1H", "1-1H", "1-1H",
                             "3-SV", "3-SV", "3-SV", "3-1V", "3-1V", "3-1V",
                             "3-1H", "3-1H", "3-1H")),
         month = factor(c("September", "October", "November", "September",
                             "October", "November", "September", "October",
                             "November", "September", "October", "November",
                             "September", "October", "November", "September",
                             "October", "November", "September", "October",
                             "November"), levels = c("September", "October", "November"))
)


Heat_clean %>%
   mutate(color = case_when(
       Days <= 5 ~ "blue",
       Days <= 15 ~ "orange",
       Days <= 25 ~ "pink",
       is.na(Days) ~ "red",
       TRUE ~ "green" # You haven't defined a color for >25
   )) %>% 
   ggplot(aes(month, Apartment_no)) + 
   geom_tile(aes(fill = color), color="white") +
   scale_fill_identity()

Created on 2019-11-21 by the reprex package (v0.3.0.9000)

1 Like

@andresrcs, @cymon, It works fine now.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.