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')
A "real-world" Beispiel:
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
mich vage erinnern versucht, dies zu tun, und googeln, dass dies durch Design vermieden wurde: https://github.com/hadley/ggplot2/issues/578 – fanli
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
Ich denke, das ist der falsche Ansatz nach einem Blick auf ggvis. – basil