2013-09-26 11 views
5

Na przykład chciałbym odwzorować kolor na z, z 0 mapami na "biały".Inne podejścia do obsługi ekstremalnych wartości/dystrybucji przy użyciu 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") 

Jak widać kolor nie jest bardzo przydatny wskaźnik, zamiast przenoszenia ogólne pojęcie o tym, w jaki sposób wartości są rozłożone, tylko teraz kolor opowiada jakie wartości są ekstremalne, pozostawiając wartości większościowe nierozróżnialne przez niewykwalifikowany oczu .

Istnieje metoda Non-linear color distribution over the range of values in a geom_raster, ale wydaje się nieco skomplikowana i mogę tylko niejasno zrozumieć, jak to działa.

enter image description here

I wtedy pomyślałem, że może order jest dobrym Przeskaluje sposób, stąd:

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

To działało do pewnego stopnia (tutaj użyłem ecdf zamiast order znaleźć to wartość 0 jest przeskalowany. Jednak wadą jest to, że chciałbym zachować etykiety legendy jako nieskalowane wartości, zamiast przeskalowanych.Tak coś takiego jak labels=function(x) quantile(a$z, x), którego nie mogę sprawić, aby działało.Również, uważam za głupie, aby wielokrotnie używać ecdf i quantile, aby przeskalować do przodu i do tyłu.

Czy istnieje lepsze lub prostsze podejście w takich przypadkach, np. solidne (nie musi być optymalne lub bardzo dokładne) wystarczy, aby wypełnić rozsądne kolory dla wszystkich rodzajów mapowanych wartości.

enter image description here

Odpowiedz

3

Nie jest łatwym sposobem, że wiem, ale można mieć pełną kontrolę nad mapowaniem z scale_fill_gradientn. Kluczem jest odwzorowanie kolorów na wartości w zakresie 0-1, gdzie 0 to minimalna wartość, a 1 to Twoja maksymalna wartość. Oto opcja:

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 

Tutaj wybieramy przypisywanie równomiernie interpolowanych kolorów do wartości na podstawie rozkładu wartości. Tak więc, jeśli zakres wartości odpowiada dużej części rozkładu, nawet jeśli faktycznie obejmuje on stosunkowo niewielką część zakresu min.-maks., Otrzyma więcej przydzielonych kolorów.

Jeśli chcesz przypisać określony kolor do zera, możesz to zrobić edytując wektory odpowiadające argumentom: colours, values i breaks. Jest to odważne, jeśli masz taką samą liczbę wartości powyżej i poniżej zera, do irytujących, jeśli nie.


wersja w/0 zestawu do bieli:

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

Powiązane problemy