3
votes

First of all I have to say that I read many threads about heatmap and ggplot2 here in stackoverflow and elsewhere. But my problem isn't solved yet.

I have got the following dataset:

   Var1   Var2 value
1 -197.5 -197.5     0
2 -192.5 -197.5     0
3 -187.5 -197.5     0
4 -182.5 -197.5     0
5 -177.5 -197.5     0
6 -172.5 -197.5     0
.....

The value should be the colour, and a legend on the right side would be nice.

library(ggplot2)
ggheatmap <- ggplot(data = dat.plot, aes(x=Var1, y=Var2, fill=value)) + 
  geom_raster()+
  scale_fill_gradientn(colours=rainbow(100))+
  theme(axis.text.x = element_text(angle = 0))+ 
  coord_fixed()
print(ggheatmap)

The result is:

Plot/Heatmap

I would like to have a "normal" rainbow scale from red=high over orange, yellow, green, light blue, dark blue=low without giving fixed discrete colours as one can do it, e.g. with scale_fill_gradient2. I wonder why "rainbow" starts with red=high end ends with some other red...

The other question: How can I add something to "smooth" the heatmap so that one doesn't see the "edges" everywhere?

3
Not answer your question but please don't use rainbow. See more here climate-lab-book.ac.uk/2014/end-of-the-rainbow & this video youtube.com/watch?v=xAoljeRJ3lUTung
O.k., I understand, but the thing is that I would like to compare my output with the one of another software which uses the rainbow palette. What I don't understand is, that (see the image there : climate-lab-book.ac.uk/2014/end-of-the-rainbow) the rainbow goes from blue to red. And if you see my legend above, even if you make rev(...), the scale starts with another kind of red, pink, and then comes blue. It's a bit strange, why it's called "rainbow" then. Or do I think wrong?Markus

3 Answers

3
votes

Short answer: function rainbow() goes nuts when you pass 100 as you're asking for 100 different colors.

What should you do: pass n to rainbow() for how many colors you want. If you want to go from blue to red then you also have to wrap it with function rev().

library(egg)
library(ggplot2)
library(reshape2)

# Heatmap number of rows/columns
Nvalue <- 1e2
# n for colors passed to function rainbow
nColor <- c(1:10, seq(20, 100, 20))
# dummy data
df <- melt(matrix(rnorm(N^2), N))

plotList <- list()
for(i in seq_along(nColor)) {
    plotList[[i]] <- ggplot(df, aes(Var1, Var2, fill = value)) + 
        geom_raster() +
        scale_fill_gradientn(colours = rev(rainbow(nColor[i]))) +
        labs(title = paste0("rainbow(", nColor[i], ")"),
             x = NULL,
             y = NULL,
             fill = NULL) +
        theme_void()
}

ggarrange(plots = plotList)

enter image description here

Edit:

After OP specified colors he wants then passing hex vector should work:

hex <- c("#FF0000", "#FFA500", "#FFFF00", "#008000", "#9999ff", "#000066")
ggplot(df, aes(Var1, Var2, fill = value)) + 
        geom_raster() +
        scale_fill_gradientn(colours = rev(hex)) +
        labs(x = NULL,
             y = NULL,
             fill = NULL) +
        theme_void()

enter image description here

3
votes

The problem of interpolating colors with a complex color scale is best illustrated on the "old faithful" data.

If you use your user defined "rainbow" color scale, the interpolation will not be doing so great (even if the result still looks quite good).

Without interpolation

library(ggplot2)
cols <- rev(rainbow(7)[-7])

ggplot(faithfuld, aes(waiting, eruptions)) +
  geom_raster(aes(fill = density), interpolate = FALSE) +
  scale_fill_gradientn(colours = cols)

Without interpolation

With interpolation

ggplot(faithfuld, aes(waiting, eruptions)) +
  geom_raster(aes(fill = density), interpolate = TRUE) +
  scale_fill_gradientn(colours = cols)

With interpolation

With interpolation and a less complex palette

ggplot(faithfuld, aes(waiting, eruptions)) +
  geom_raster(aes(fill = density), interpolate = TRUE) +
  scale_fill_gradientn(colours = c("steelblue", "tomato"))

Two color palette

0
votes
ggheatmap <- ggplot(data = dat.plot, aes(x=Var1, y=Var2, fill=value)) + 
  geom_raster(interpolate=TRUE)+
  scale_fill_gradientn(colors=rev(c("darkred", "red", "orange", "yellow",    "green", "lightgreen", "lightblue", "darkblue")))+
  theme(axis.text.x = element_text(angle = 0))+ 
  coord_fixed()
print(ggheatmap)

Now it looks blurred. But o.k. If you think it can't be done better, I let it as it is. Thank you very much!