3

I'm trying to increase the speed of my R Leaflet map by reducing the size of the polygons.

I found a great solution on stack exchange here, but for some reason, I get the following error when I try to plot the shapes. "Error in pgons@Polygons[[index]] : subscript out of bounds"

I'm guessing the issue stems from the getSmallPolys function, but I don't know how to fix it. If this would work, it would increase the speed of my Leaflet map a lot.

library(sp)
library(rgeos)
library(raster)
library(leaflet)
library(readr)
# Source of getSmallPolys function: "https://gis.stackexchange.com/questions/62292/how-to-speed-up-the-plotting-of-polygons-in-r"

# Get the main polygons, will determine by area.
getSmallPolys <- function(poly, minarea=0.01) {
  # Get the areas
  areas <- lapply(poly@polygons, 
                  function(x) sapply(x@Polygons, function(y) y@area))

  # Quick summary of the areas
  print(quantile(unlist(areas)))

  # Which are the big polygons?
  bigpolys <- lapply(areas, function(x) which(x > minarea))
  length(unlist(bigpolys))

  # Get only the big polygons and extract them
  for(i in 1:length(bigpolys)){
    if(length(bigpolys[[i]]) >= 1 && bigpolys[[i]] >= 1){
      poly@polygons[[i]]@Polygons <- poly@polygons[[i]]@Polygons[bigpolys[[i]]]
      poly@polygons[[i]]@plotOrder <- 1:length(poly@polygons[[i]]@Polygons)
    }
  }
  return(poly)
}

AUS <- getData("GADM", country = "AUS", level = 1)
CAN <- getData("GADM", country = "CAN", level = 1)
USA <- getData("GADM", country = "USA", level = 1)
GBR <- getData("GADM", country = "GBR", level = 1)
shape <- 
  rbind(AUS, CAN, USA, GBR)

# From 195 mb to 78.7 mb (32.1 mb if filtered)
shapesSimple <-
  gSimplify(shape, tol=0.1, topologyPreserve=TRUE) %>%
  SpatialPolygonsDataFrame(., data = shape@data)

# This would be ideal for render speed but I get an error when I try to plot it
# From 195 mb to 1.9 mb (1 mb if filtered)
shapesSimple <-
  gSimplify(shape, tol=0.1, topologyPreserve=TRUE) %>%
  getSmallPolys() %>%
  SpatialPolygonsDataFrame(., data = shape@data)

# Testing the speed
start_time <- Sys.time()
leaflet() %>% 
  addTiles() %>% 
  addPolygons(data = shapesSimple)
end_time <- Sys.time()
end_time - start_time
1
  • Depending on the complexity of the geometries, it's sometimes faster to render more shapes than fewer, if the features in the viewfield have fewer vertices.
    – Vince
    Aug 22, 2019 at 1:03

1 Answer 1

1

So I found a better solution with less code. All I had to do was use the ms_simplify function from the rmapshaper package after using the gSimplify function. The shapes load super fast now.

library(sp)
library(rgeos)
library(readr)
library(raster)
library(leaflet)
library(rmapshaper)

AUS <- getData("GADM", country = "AUS", level = 1)
CAN <- getData("GADM", country = "CAN", level = 1)
USA <- getData("GADM", country = "USA", level = 1)
GBR <- getData("GADM", country = "GBR", level = 1)

shape <- 
  rbind(AUS, CAN, USA, GBR)
shape <- 
  subset(shape, NAME_1 %in% unique(final$stateName))

# From 195 mb to 1.1 mb
# This is so much faster!
shapesSimple <-
  gSimplify(shape, tol=0.1, topologyPreserve=TRUE) %>% 
  SpatialPolygonsDataFrame(., data = shape@data) %>% 
  ms_simplify()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.