2016-03-30 11 views
4

Ich habe zwei Raster-Ebenen, eine ist ein Graustufenbild und die andere ergibt sich aus einer Analyse. Ich würde gerne ein Raster als Graustufenhintergrund in ggplot verwenden und das zweite Raster mit einer Farbrampe überlagern. Dies ist ein Beispiel, wie es aussehen könnte (aber schöner):R - ggplot2 - verwende Raster als Graustufen-Grundkarte

enter image description here

Ich kann nicht einzelne Farben zu den Rastern zuweisen. Kennst du einen Weg, dies zu erreichen? Ich habe lange gegoogelt und ich habe den Eindruck, dass das nicht möglich ist. Aber ich kann (und will es nicht) glauben.

Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

Beispiel

erstellen Datentest

xy.1 <- expand.grid(1:10, 1:10) 
df.1 <- data.frame(Longitude=xy.1[,1], Latitude=xy.1[,2], Value=xy.1[,1]+xy.1[,2]) 
xy.2 <- expand.grid(3:5, 3:5) 
df.2 <- data.frame(Longitude=xy.2[,1], Latitude=xy.2[,2], Value=rnorm(9)) 

Grundstück

p1 <- ggplot() + 
    geom_raster(data=df.1, aes(x=Longitude, y=Latitude, fill=Value)) + 
    scale_fill_gradientn(colours = grey(seq(0,1,l=20))) + 
    coord_equal() + 
    theme(legend.position="none") 

p1 + geom_raster(data=df.2, aes(x=Longitude, y=Latitude, fill=Value)) + 
    scale_fill_gradient(low="red", high="white") 

Ergebnis:

enter image description here

+2

mich vage erinnern versucht, dies zu tun, und googeln, dass dies durch Design vermieden wurde: https://github.com/hadley/ggplot2/issues/578 – fanli

+0

Dank Fanli für deine Antwort. Ich habe den Link überprüft und der letzte Kommentar besagt, dass ggvis dies unterstützt. Ich werde versuchen, es mit ggvis zu tun, und ich werde die Antwort posten, wenn es funktioniert. – basil

+0

Ich denke, das ist der falsche Ansatz nach einem Blick auf ggvis. – basil

Antwort

2

Ich habe eine Funktion geschrieben, mit der man einen Hintergrund hinzufügen und ein Vordergrund-Raster mit ggplot2 überlagern kann.

Edit: Ich habe eine bessere Lösung am Ende

Dies ist, wie es funktioniert:

ich die beiden Rastern kombinieren und die Werte verschieben, so dass die Werte nicht überlappen. Dann plotte ich die Rasterebene mit einer Skalierung, die die Farbskala für den Vordergrund enthält (z. B. rot -> grün), wobei die Hintergrundfarbskala fest codiert ist (schwarz -> weiß). Die Anzahl der Farben ist unbegrenzt.

Die Legende der Rasterebene wird nicht angezeigt. Um eine Legende zu erhalten, die nicht den gesamten Maßstab enthält (das wäre schwarz -> weiß -> rot -> grün), füge ich zwei Dummy-Punkte in den Hintergrund ein. Eines mit dem kleinsten Wert der Vordergrunddaten, eines mit dem größten. Dies ergibt eine Legende nur für die Vordergrunddaten.

Wenn jemand einen schöneren Weg zum Skalieren und Erstellen der Farbskala kennt, würde ich das gerne der Funktion hinzufügen.

Ich habe die Möglichkeit hinzugefügt, die Vordergrunddaten mit Quantilen zu skalieren; Das Argument fg.quant verwendet einen Vektor aus zwei Ganzzahlen, der zum "Schneiden" der Daten verwendet wird. bw.scale ermöglicht, das Hintergrundraster dunkler/heller zu machen: bw.scale=c(0, 0.5) bedeutet, dass das Hintergrundbild beispielsweise eine Farbskala von Schwarz bis Grau (0,5) hat.

Ich weiß, dass dies keine perfekte Funktion ist. Aber es ist sehr nützlich für mich und ich werde es verbessern und versuchen, die hässlichen Teile zu beseitigen, sobald ich etwas Freizeit habe.

Testdaten

# 'background' 
r.1 <- raster(x=matrix(rowSums(expand.grid(1:10, 1:10)), nrow=10), 
       xmn=0, xmx=10, ymn=0, ymx=10) 
# 'foreground' 
r.2 <- raster(x=matrix(rnorm(16), nrow=4), 
       xmn=3, xmx=7, ymn=3, ymx=7) 

Plotfunktion

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
# BGPlot() -- plot data with background raster using ggplot2 
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

BGPlot <- function(fg, 
        bg, 
        cols=c('red', 'green'), 
        fg.quant=c(0, 1), 
        bw.scale=c(0, 1), 
        plot.title='', 
        leg.name='Value') { 
    # plot data with background raster using ggplot2 
    # 
    # Args 
    # fg: foreground raster layer 
    # bg: background raster layer 
    # cols: colors to use for fg 
    # fg.quant: scaling fg by quantiles 
    # bw.scale: makes bg darker/brighter: 
    #  E.g. c(0, 0.9) -> darker/c(0.2, 1) -> brighter 
    # plot.title: title 
    # leg.name: name to be displyed at legend 
    # 
    # Returns 
    # ggplot object 

    # load libraries 
    library(ggplot2) 

    # get min/max of foreground raster 
    fg.q <- quantile(fg, fg.quant) 
    fg.min <- fg.q[1] 
    fg.max <- fg.q[2] 

    # rescale fg 
    fg.sc <- (fg-fg.q[1])/(fg.q[2]-fg.q[1]) 
    fg.sc[fg.sc<0] <- 0 
    fg.sc[fg.sc>1] <- 1 
    fg.sc <- fg.sc + 0.1 

    # get scale (fg values 0.1, 10, 1000 range?) 
    ifelse((fg.max-fg.min)/10>=1, n.dgts <- 0, n.dgts <- 1) 

    # create fg legend breaks/labels 
    fg.breaks <- round(seq(fg.min, fg.max, l=5), n.dgts) 
    fg.breaks[1] <- ceiling(fg.min*(10^n.dgts))/(10^n.dgts) 
    fg.breaks[5] <- floor(fg.max*(10^n.dgts))/(10^n.dgts) 

    fg.labs <- paste0(c(paste0(round(fg.min, n.dgts+1), '-'),'','','',''), 
        fg.breaks, 
        c('','','','',paste0('-', round(fg.max, n.dgts+1))) 
) 


    # rescale bg 
    bg.sc <- (bg-minValue(bg))/
    (maxValue(bg)-minValue(bg)) * 
    (bw.scale[2]-bw.scale[1]) + bw.scale[1] -1.1 


    # merge rasters, fg over bg 
    r <- merge(fg.sc, bg.sc) 

    # convert raster to data.frame 
    r.df <- as.data.frame(rasterToPoints(r)) 
    names(r.df) <- c('Longitude', 'Latitude', 'Value') 

    # get center of r 
    mid.Lon <- mean(r.df$Longitude) 
    mid.Lat <- mean(r.df$Latitude) 

    # set scale positions 
    vals <-c(-1.1,-0.1, seq(0.1,1.1,l=length(cols))) 

    # set dummy-point values 
    dp <-seq(fg.min,fg.max,l=length(cols)) 


    # plotting; 
    p <- 
    ggplot() + 
    # dummy points: points not visible, needed to display custom scale-bar 
    geom_point(data=data.frame(x = rep(mid.Lon, length(cols)), 
           y = rep(mid.Lat, length(cols)), 
           c = dp), 
       aes(x, y, color=c)) + 
    scale_color_gradientn(colours = cols, 
          breaks=fg.breaks, 
          labels=fg.labs, 
          name=leg.name) + 
    # raster; no scale-bar plotted 
    geom_raster(data=r.df, aes(x=Longitude, y=Latitude, fill=Value)) + 
    scale_fill_gradientn(colours = c('black', 'white', cols), 
         values = vals, 
         rescaler = function(x,...) x, 
         oob  = identity, 
         guide = "none") + 
    ggtitle(label=plot.title) + 
    theme_light() + 
    labs(list(x='Lon', y='Lat')) + 
    theme(axis.text.y=element_text(angle=90, hjust=0.5)) + 
    coord_equal() 

    return(p) 
} 

Funktionsaufruf

BGPlot(fg=r.2, bg=r.1, cols=c('red', 'green'), fg.quant=c(0.01, 0.99), bw.scale=c(0, 0.8), plot.title='Chlorophyll Concentration', leg.name='CHL') 

enter image description here

A "real-world" Beispiel:

enter image description here

EDIT: Bessere Lösung unter Verwendung von R-Paket 'RStoolbox'

Dies ist eine sehr einfache und perfekte Arbeitslösung des Paket mit RStoolbox. Die Funktion ggR erzeugt ein Graustufen-Hintergrundbild, Funktion ggRGB einen RGB-Hintergrund.

library(ggplot2) 
library(RStoolbox) 
ggR(BACKGROUND_IMAGE, geom_raster=FALSE) + 
geom_raster(...) # here comes standard raster plot