2013-09-26 5 views
5

Ad esempio, desidero mappare il colore su z, con 0 mappe su "bianco".Altri approcci per gestire valori estremi/distribuzione quando si utilizza scale_fill_gradient?

> a <- data.frame(x=1:10, y=1, z=c(rnorm(8),-12,12)) 
> a 
    x y   z 
1 1 1 -0.4603911 
2 2 1 -0.4868471 
3 3 1 0.2180346 
4 4 1 -0.8807652 
5 5 1 1.7379462 
6 6 1 -0.1334904 
7 7 1 -0.3675578 
8 8 1 0.9225425 
9 9 1 -12.0000000 
10 10 1 12.0000000 

ggplot(a,aes(x=x,y=y,fill=z)) + geom_bar(stat="identity") + 
    scale_fill_gradient2(high="green", mid="white", low="red") 

Come si può vedere il colore non è molto utile indicatore, invece di trasmettere un'idea generale di come sono distribuiti i valori, ora il colore dice solo che i valori sono estreme, lasciando i valori di maggioranza indistinguibili da occhi inesperti .

C'è un metodo Non-linear color distribution over the range of values in a geom_raster ma sembra un po 'complicato e posso solo capire vagamente come funziona.

enter image description here

Allora ho pensato che forse order è un buon modo Rescale, quindi:

ggplot(a,aes(x=x,y=y,fill=ecdf(z)(z))) + geom_bar(stat="identity") + 
scale_fill_gradient2(high="green", mid="white", low="red", midpoint=ecdf(a$z)(0)) 

ha funzionato in una certa misura (qui ho usato ecdf invece di order per trovare quale valore 0 viene ridimensionata. Tuttavia, lo svantaggio è che vorrei conservare le etichette della legenda come valori non graduati, invece di quelli riscalati, quindi qualcosa come labels=function(x) quantile(a$z, x), che non riesco a far funzionare, inoltre trovo stupido usare ripetutamente ecdf e quantile per eseguire il ridimensionamento in avanti e all'indietro.

Esiste un approccio migliore o più semplice in questi casi, ad es. robusto (non deve essere ottimale o molto preciso) abbastanza da riempire colori ragionevoli per tutti i tipi di distribuzioni di valori mappati.

enter image description here

risposta

3

Non c'è un modo semplice, che io sappia, ma è possibile avere il pieno controllo della mappatura con scale_fill_gradientn. La chiave è mappare i colori ai valori nell'intervallo 0-1 dove 0 è il valore minimo e 1 è il valore massimo. Ecco un'opzione:

library(ggplot2) 
a <- data.frame(x=1:10, y=1, z=c(rnorm(8),-12,12)) 
get_col <- colorRamp(c("red", "white", "green")) # make fun to interpolate colors 
quantiles <- (0:6)/6       # how many quantiles we want to map 
quantile.vals <- quantile(a$z, quantiles, names=F)# the values for each quantile 
colours <- rgb(get_col(quantiles), max=255)  # 7 evenly interpolated colors 
val.remap <- (quantile.vals - min(a$z))/
    diff(range(a$z))        # The values corresponding to the quantiles 

ggplot(a, aes(x=x,y=y,fill=z)) + 
    geom_bar(stat="identity") + 
    scale_fill_gradientn(
    colours=colours, 
    values=val.remap, 
    breaks=quantile.vals,# Necessary to get legend values spread appropriately 
    guide="legend")  # Necessary to get legend values spread appropriately 

Qui abbiamo scelto di assegnare colori interpolati in modo uniforme ai valori basati sulla distribuzione dei valori. Quindi, se un intervallo di valori corrisponde a gran parte di una distribuzione, anche se essa si estende su una porzione relativamente piccola dell'intervallo min-max, otterrà più colore assegnato.

Se si desidera assegnare un colore specifico a zero, è possibile farlo modificando i vettori corrispondenti agli argomenti colours, values e breaks. Questo va da banale se si ha lo stesso numero di valori sopra e sotto lo zero, a fastidioso se non.


Versione w/0 insieme al bianco:

library(ggplot2) 
a <- data.frame(x=1:10, y=1, z=c(rnorm(8), -12, 12)) 
splits <- 7  # should be odd number 
mid.point <- 0 
pos.vals <- a$z[a$z > mid.point] 
neg.vals <- a$z[a$z < mid.point] 
pos.quants <- quantile(c(mid.point, pos.vals), 0:((splits - 1)/2)/((splits - 1)/2), names=F) 
neg.quants <- quantile(c(mid.point, neg.vals), 0:((splits - 1)/2)/((splits - 1)/2), names=F) 
quants <- c(neg.quants, pos.quants[-1]) # drop of the mid-point from pos.quants since otherwise double counted 

get_col <- colorRamp(c("red", "white", "green")) # make fun to interpolate colors 
colours <- rgb(get_col(0:(splits - 1)/(splits - 1)), max=255)  # 7 evenly interpolated colors 
val.remap <- (quants - min(quants))/
    diff(range(quants))        # The values corresponding to the quantiles 

ggplot(a, aes(x=x,y=y,fill=z)) + 
    geom_bar(stat="identity") + 
    scale_fill_gradientn(
    colours=colours, 
    values=val.remap, 
    breaks=quants, 
    guide="legend") 

color mapping result http://i42.tinypic.com/qzmzgn.png

Problemi correlati