Search code examples
rgeospatialrastershapefiler-sp

Why does spplot take so much time for multiple panels


I am plotting multiple shapefiles using spplot. Here's a data to construct that

library(raster)
library(randomcoloR)

my.shp <- getData('GADM', country = 'BRA', level = 2)
my.shp$ID<- 1:nrow(my.shp)

My data consists of a variable X for 10 years as shown where each column is a year

df <- matrix(sample(100:5000, 55040, replace = T), nrow = 5504, ncol = 10)
df <- data.frame(ID = 1:nrow(my.shp), df)

my.dat <- merge(my.shp, df, by = "ID")

variable.names <- paste0("X",1:10)

spplot(my.dat, rev(variable.names), col = NA, at = seq(from = 100, to = 5000, by = 500), 
          col.regions = distinctColorPalette(length(seq(from = 100, to = 5000, by = 500))),
          main = list(label = "TEST")) 

My problem is this plot takes so much time (around an hour) to get plotted and was wondering if there is something inherently wrong in the code itself that it is taking too long to plot. My laptop has a 32 GB RAM.

Thanks


Solution

  • Are you willing/able to switch to sf instead of sp?

    The sf plot function is considerably faster than spplot, although the layout differs a bit.

    library(sf)
    my.dat_sf <- st_as_sf(my.dat)
    plot(my.dat_sf[rev(variable.names)], max.plot=10, breaks=c(seq(from = 100, to = 5000, by = 500),5000),
         pal = distinctColorPalette(length(seq(from = 100, to = 5000, by = 500))),
         main = "TEST", border=NA, key.pos=4)
    

    Additionally, you could try to simplify the polygon with rmapshaper::ms_simplify() for Spatial*-objects or sf::st_simplify() for SimpleFeatures, which lets you reduce the object size by quite a bit, depending on the given dTolerance. Thus plotting, will also be faster with simplified polygons.

    The original SpatialPolygon:

    format(object.size(my.dat_sf), units="Kb")
    

    "25599.2 Kb"

    and a simplified SimpleFeature:

    dat_sf_simple <- st_transform(my.dat_sf, crs = 3035)
    dat_sf_simple <- st_simplify(dat_sf_simple, dTolerance = 1000, preserveTopology = T)
    dat_sf_simple <- st_transform(dat_sf_simple, crs = 4326)
    format(object.size(dat_sf_simple), units="Kb")
    

    "7864.2 Kb"

    Plot the simplified SimpleFeature, which takes about 1 minute on my machine with 8GB RAM.

    plot(dat_sf_simple[rev(variable.names)], max.plot=10, breaks=c(seq(from = 100, to = 5000, by = 500),5000),
         pal = distinctColorPalette(length(seq(from = 100, to = 5000, by = 500))),
         main = "TEST", border=NA, key.pos=4)
    

    You could also try out with ggplot2, but I am pretty sure the most performant solution will be the sf plot.

    library(ggplot2)
    library(dplyr)
    library(tidyr)
    
    dat_sf_simple_gg <- dat_sf_simple %>% 
      dplyr::select(rev(variable.names), geometry) %>% 
      gather(VAR, SID, -geometry)
    
    ggplot() +
      geom_sf(data = dat_sf_simple_gg, aes(fill=SID)) + 
      facet_wrap(~VAR, ncol = 2)