2017-06-19 5 views
1

Ich versuche, einige globale Karten (Raster-Dateien) zu plotten und ich habe einige Probleme beim Einrichten einer guten Farbskala für meine Daten. Was ich tun möchte, ist, meine Daten mit einer abweichenden Palette zu plotten (zB cm.colors), und ich möchte die Farbe "weiß" eines solchen Maßstabs mit dem Wert Null zentrieren, aber ohne symmetrische Werte in der Skala (dh der gleiche Wert ist sowohl negativ als auch positiv, dh limits=c(-1,1)). Außerdem möchte ich alle Werte über und/oder unter einem bestimmten Wert alle mit der gleichen Farbe plotten. Wenn wir annehmen, dass meine Karte einen Bereich von -100 bis 150 hat, möchte ich meine Karte mit einer divergierenden Palette mit einer "weißen" Farbe entsprechend dem Wert 0 und mit allen Werten darstellen z.B unter -20 und über 50 aufgetragen mit der gleichen Farbe, d.h. jeweils mit den negativen und positiven Extremen der Farbpalette.ggplot2: Umgang mit extremen Werten durch Einstellung einer kontinuierlichen Farbskala

Hier ein Beispiel für den Code, den ich für den Moment bin mit:

ggplot(df, aes(y=Latitude, x=Longitude)) + 
    geom_raster(aes(fill=MAP)) + 
    coord_equal()+ 
    theme_gray() + 
    theme(panel.background = element_rect(fill = 'skyblue2', colour = 'black'), 
     panel.grid.major = element_blank(), 
     panel.grid.minor = element_blank(), 
     legend.position = "right", 
     legend.key = element_blank()) + 
    scale_fill_gradientn("MAP", limits=c(-0.5,1), colours=cm.colors(20)) 

Antwort

2

Es gibt einfache Möglichkeiten, dies zu tun, wie Sie Ihre Daten vorher Kürzen oder mit cut diskreten Bins für entsprechende Etiketten erstellen .

require(dplyr) 
df %>% mutate(z2 = ifelse(z > 50, 50, ifelse(z < -20, -20, z))) %>% 
    ggplot(aes(x, y, fill = z2)) + geom_tile() + 
    scale_fill_gradient2(low = cm.colors(20)[1], high = cm.colors(20)[20]) 

enter image description here

df %>% mutate(z2 = cut(z, c(-Inf, seq(-20, 50, by = 10), Inf)), 
       z3 = as.numeric(z2)-3) %>% 
    {ggplot(., aes(x, y, fill = z3)) + geom_tile() + 
    scale_fill_gradient2(low = cm.colors(20)[1], high = cm.colors(20)[20], 
         breaks = unique(.$z3), labels = unique(.$z2))} 

enter image description here

Aber ich hatte gedacht, zu dieser Aufgabe vor und fühlte sich damit nicht zufrieden. Das Vorabschneiden hinterlässt keine schönen Beschriftungen, und die Option ist immer fummelig (insbesondere müssen Sie die Parameter seq innerhalb anpassen und herausfinden, wie die Bins neu zentriert werden). Daher habe ich versucht, eine wiederverwendbare Transformation zu definieren, die das Abschneiden und Umbenennen für Sie übernimmt.

Ich habe nicht vollständig debugged und ich gehe aus der Stadt, so hoffentlich können Sie oder ein anderer Antworter einen Riss bei ihm machen. Das Hauptproblem scheint Kollisionen in den Randfällen zu sein, so dass gelegentlich die Grenzen die beabsichtigten Unterbrechungen visuell überlappen, ebenso wie ein unerwartetes Verhalten bei der Formatierung. Ich habe gerade Dummy-Daten verwendet, um den gewünschten Bereich von -100 bis 150 zu erstellen, um es zu testen.

require(scales) 
trim_tails <- function(range = c(-Inf, Inf)) trans_new("trim_tails", 
       transform = function(x) { 
        force(range) 
        desired_breaks <- extended_breaks(n = 7)(x[x >= range[1] & x <= range[2]]) 
        break_increment <- diff(desired_breaks)[1] 
        x[x < range[1]] <- range[1] - break_increment 
        x[x > range[2]] <- range[2] + break_increment 
        x 
       }, 
       inverse = function(x) x, 

       breaks = function(x) { 
        force(range) 
        extended_breaks(n = 7)(x) 
       }, 
       format = function(x) { 
        force(range) 
        x[1] <- paste("<", range[1]) 
        x[length(x)] <- paste(">", range[2]) 
        x 
       }) 

ggplot(df, aes(x, y, fill = z)) + geom_tile() + 
    guides(fill = guide_colorbar(label.hjust = 1)) + 
    scale_fill_gradient2(low = cm.colors(20)[1], high = cm.colors(20)[20], 
         trans = trim_tails(range = c(-20,50))) 

enter image description here

arbeitet auch mit einer Box-Legende anstelle eines colorbar, benutzen Sie einfach ... + guides(fill = guide_legend(label.hjust = 1, reverse = T)) + ...

enter image description here

+0

Große, voll Antwort Brian konkretisiert. Danke dafür. Ich brauche es jetzt nicht, aber ich konnte sehen, dass die Transformation äußerst praktisch ist. – SeldomSeenSlim

Verwandte Themen