How to specify “low” and “high” and get two scales at two ends using scale_fill_gradient

My question is: I want a diverging color for my geom_tile using geom_tile , and the gradient color changes at both ends of the scale. For example, the whole scale is (-1.1), I only need values ​​from -1 to -0.5, and values ​​from 0.5 to 1.0 have a gradient color change, and values ​​from -0.5 to 0, 5 remain white. However, I cannot find an option in scale_fill_gradient to achieve the goal. A reproducible example is given below and data is obtained from ggplot2 heatmaps: using different gradients for categories

 nba <- read.csv("http://datasets.flowingdata.com/ppg2008.csv") nba$Name <- with(nba, reorder(Name, PTS)) library("ggplot2") library("plyr") library("reshape2") library("scales") nba.m <- melt(nba) nba.s <- ddply(nba.m, .(variable), transform, rescale = scale(value)) ggplot(nba.s, aes(variable, Name))+geom_tile(aes(fill = rescale), colour = "white") + scale_fill_gradient(low = "darkgreen", high = "darkred") 
+7
colors r ggplot2 scale heatmap
source share
1 answer

You can try adding a white middle to scale_fill_gradient2 :

 gg <- ggplot(nba.s, aes(variable, Name)) gg <- gg + geom_tile(aes(fill = rescale), colour = "white") gg <- gg + scale_fill_gradient2(low = "darkgreen", mid = "white", high = "darkred") gg <- gg + labs(x="", y="") gg <- gg + theme_bw() gg <- gg + theme(panel.grid=element_blank(), panel.border=element_blank()) gg 

enter image description here

But you will have maximum flexibility if you respond to the response in the SO message you contacted and use scale_fill_gradientn .

EDIT (to show an example from a discussion of comments)

 # change the "by" for more granular levels green_seq <- seq(-5,-2.000001, by=0.1) red_seq <- seq(2.00001, 5, by=0.1) nba.s$cuts <- factor(as.numeric(cut(nba.s$rescale, c(green_seq, -2, 2, red_seq), include.lowest=TRUE))) # find "white" white_level <- as.numeric(as.character(unique(nba.s[nba.s$rescale >= -2 & nba.s$rescale <= 2,]$cuts))) all_levels <- sort(as.numeric(as.character(unique(nba.s$cuts)))) num_green <- sum(all_levels < white_level) num_red <- sum(all_levels > white_level) greens <- colorRampPalette(c("#006837", "#a6d96a")) reds <- colorRampPalette(c("#fdae61", "#a50026")) gg <- ggplot(nba.s, aes(variable, Name)) gg <- gg + geom_tile(aes(fill = cuts), colour = "white") gg <- gg + scale_fill_manual(values=c(greens(num_green), "white", reds(num_red))) gg <- gg + labs(x="", y="") gg <- gg + theme_bw() gg <- gg + theme(panel.grid=element_blank(), panel.border=element_blank()) gg <- gg + theme(legend.position="bottom") gg 

enter image description here

The legend is far from ideal, but you can potentially exclude it or bypass it in other ways.

+9
source share

All Articles