[GIS] Inserting zoomed-in plot with full scale plot in sp package in R

plotrspzoom

I am using the sp package in R to plot sampled points along a river. However, I would like to zoom in to a sampled area of the entire river, and plot this zoomed area on the full length of the river. Using the spplot function is useful, as I have various variables per point. To "zoom" in, I can simple change the ylim and xlim arguments when using the spplot function.

Using the meuse dataset as an example

library(sp)
library(lattice) 
data(meuse)
coordinates(meuse)=~x+y 
FUll.study<-spplot(meuse)            #Gives the full study area
ZOOM<-spplot(meuse, xlim=c(170000,  181000), ylim=c(329714,333611))   #Random area to zoom in.

The results look like this:

enter image description here

However the desired result is something like this:

enter image description here
I am trying to find a way to add the ZOOM to an area on the Full.study map.I suspect because spplot is dependent on lattice it may not be possible. In that case, I would have to create a map for each variable independently, and add the respective zoomed area, probably through par(new=TRUE), but this is just a thought. I would still have to figure out how to specify the location and adjust the size of the of zoomed area.

Best Answer

Here is a suggestion using ggplot. I use ggplotGrob to combine the full and zoomed map and grid.arrange from the gridExtra add-on to combine the maps for different variables. There are many adjustments that can be made, of course.

library(sp)
library(ggplot2)
library(grid) # for unit
library(gridExtra) # for grid.arrange

# zoom bounding box
xlim <- c(179500,181000); ylim <- c(332000,332500)

# size of zoomed area - offset from top left corner of main plot: 
x_offs <- 1000 ; y_offs <- 1300

# settings for full plot
fulltheme <- theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), 
            panel.background = element_blank(), 
            axis.text.x=element_blank(), axis.text.y=element_blank(),
            axis.ticks=element_blank(),
            axis.title.x=element_blank(), axis.title.y=element_blank())

# settings for zoom plot
zoomtheme <- theme(legend.position="none", axis.line=element_blank(),axis.text.x=element_blank(),
            axis.text.y=element_blank(),axis.ticks=element_blank(),
            axis.title.x=element_blank(),axis.title.y=element_blank(),
            panel.grid.major = element_blank(), panel.grid.minor = element_blank(), 
            panel.background = element_rect(color='red', fill="white"),
            plot.margin = unit(c(0,0,-6,-6),"mm"))


############## point example  #############
data(meuse)

# variables to plot
vars <- names(meuse)[3:10]

plotlist <- list()

for (i in vars) {
  # full plot
  p.full <- ggplot(meuse, aes_string(x = "x", y = "y", color=i)) + 
    geom_point() + fulltheme
  # zoomed plot
  p.zoom <- ggplot(meuse, aes_string(x = "x", y = "y", color=i)) + 
    geom_point() + coord_cartesian(xlim=xlim, ylim=ylim) + zoomtheme
  # put them together
  g <- ggplotGrob(p.zoom)
  plotlist[[length(plotlist) + 1]] <- p.full + 
    annotation_custom(grob = g, xmin = min(meuse$x), xmax = min(meuse$x) + x_offs, ymin = max(meuse$y) - y_offs, ymax = max(meuse$y))
}

# plot
do.call(grid.arrange,  c(plotlist, ncol=4))

enter image description here

Similarly, ggplot can handle rasters.

############################################
############## raster example  #############

library(raster)

r <- raster(system.file("external/test.grd", package="raster"))
s <- stack(r, r*2, log(r))
names(s) <- c('meuse', 'meuse2', 'meuseLog')
meuseRast <- data.frame(rasterToPoints(s))

rastvars <- names(meuseRast)[-c(1:2)]
plotrast <- list()

for (i in rastvars) {
   p.fullrast <- ggplot(meuseRast, aes_string(x = "x", y = "y", fill = i)) + 
      geom_raster() + fulltheme

   p.zoomrast <- ggplot(meuseRast, aes_string(x = "x", y = "y", fill = i)) + 
      geom_raster() + coord_cartesian(xlim=xlim, ylim=ylim) + zoomtheme

   g <- ggplotGrob(p.zoomrast)
   plotrast[[length(plotrast) + 1]] <- p.fullrast + 
     annotation_custom(grob = g, xmin = min(meuseRast$x), xmax = min(meuseRast$x) + x_offs, ymin = max(meuseRast$y) - y_offs, ymax = max(meuseRast$y))
}

# plot
do.call(grid.arrange,  c(plotrast, nrow=1))

enter image description here

Related Question