Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 716
89_Simple Avatar asked Feb 04 '26 11:02

89_Simple


2 Answers

I haven't compared this plot to your spplot because I don't want to spend an hour waiting for it.

Instead I'm proposing to use library(mapdeck) to plot an interactive map, which takes a matter of seconds.

Two things to note

  1. You need a Mapbox Access token
  2. You need to convert the sp object to sf
library(raster)

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

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")


library(sf)
sf <- sf::st_as_sf( my.dat )

library(mapdeck)

set_token( "YOUR_MAPBOX_TOKEN" )

mapdeck() %>% 
  add_sf(
    data = sf
    , fill_colour = "GID_2"
    )

enter image description here

like image 116
SymbolixAU Avatar answered Feb 06 '26 03:02

SymbolixAU


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) 
like image 23
SeGa Avatar answered Feb 06 '26 03:02

SeGa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!