Как да посочите ниско и високо и да получите две скали в двата края с помощта на scale_fill_gradient

Въпросът ми е, че искам различен цвят за моята топлинна карта, използвайки geom_tile и цветът на градиента варира в двата края на скалата. Например, цялата скала е (-1,1), искам само стойностите от -1 до -0,5 и стойностите от 0,5 до 1,0 имат градиентна цветова вариация, а стойностите между -0,5 и 0,5 остават бели. Въпреки това не мога да намеря опция в scale_fill_gradient за постигане на целта. Възпроизводим пример е както по-долу и данните са от ggplot2 heatmaps: използване на различни градиенти за категории

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") 

person MYjx    schedule 15.10.2014    source източник


Отговори (1)


Можете да опитате да добавите бяла средна точка към 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

въведете описание на изображението тук

Но ще имате най-голяма гъвкавост, ако следвате отговора в SO публикацията, към която сте се свързали, и използвате scale_fill_gradientn.

РЕДАКТИРАНЕ (за показване на пример от дискусията за коментари)

# 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

въведете описание на изображението тук

Легендата далеч не е идеална, но потенциално можете да я изключите или да я заобиколите чрез други средства.

person hrbrmstr    schedule 15.10.2014
comment
Благодаря за отговора! Искам обаче всички стойности, в този случай от -2 до 2, да станат изцяло бели без градиентен ефект... - person MYjx; 15.10.2014
comment
ако това и решението gradientn не работят, тогава ще трябва да направите свои собствени cut от стойностите и ръчно да посочите градиентните цветове с scale_fill_manual. - person hrbrmstr; 15.10.2014
comment
да, опитах scale_fill_manual, свърши работа, но не искам да посочвам цвета всеки път, тъй като имам много данни всеки ден. Ето защо искам да използвам gradientn. Опитах се да използвам breaks, но изглежда работи само за легендата, а не за самия цвят. - person MYjx; 15.10.2014
comment
Вие можете да създадете две функции за цветна рампа - greens <- colorRampPalette(c("#006837", "#a6d96a")) и reds <- colorRampPalette(c("#fdae61", "#a50026")), след което да направите толкова гранулиран cut, колкото искате (запазвайки диапазона -2:2 непокътнат), да изчислите # нива под и отгоре и да преминете ги включете като параметри към тези два генератора на палитри и много програмно изградете ръчната цветова скала. - person hrbrmstr; 15.10.2014
comment
Мерси! @hrbrmstr Всъщност имах възможност да говоря с Хадли Уикман днес и той също нямаше просто решение. Мисля, че в този момент това е най-добрият начин да се справите с това! :) - person MYjx; 17.10.2014