rmapshaper is a package which is an R wrapper around the awesome mapshaper tool by Matthew Bloch, which has both a Node.js command-line tool as well as an interactive web tool.
The main advantage of the package is the availability of the
topologically-aware simplification algorithm in ms_simplify
(provided by the simplify
tool in mapshaper). This means
that shared boundaries between adjacent polygons are always kept intact,
with no gaps or overlaps, even at high levels of simplification. It uses
the Visvalingam
simplification method.
At this time, rmapshaper
provides the following
functions:
ms_simplify
- simplify polygons or linesms_clip
- clip an area out of a layer using a polygon
layer or a bounding box. Works on polygons, lines, and pointsms_erase
- erase an area from a layer using a polygon
layer or a bounding box. Works on polygons, lines, and pointsms_dissolve
- aggregate polygon features, optionally
specifying a field to aggregate on. If no field is specified, will merge
all polygons into one.ms_explode
- convert multipart shapes to single part.
Works with polygons, lines, and points in geojson format, but currently
only with polygons and lines in the Spatial
classes (not
SpatialMultiPoints
and
SpatialMultiPointsDataFrame
).ms_lines
- convert polygons to topological boundaries
(lines)ms_innerlines
- convert polygons to shared inner
boundaries (lines)ms_points
- create points from a polygon layerms_filter_fields
- Remove fields from the
attributesms_filter_islands
- Remove small detached polygonsThis short vignette focuses on simplifying polygons with the
ms_simplify
function.
rmapshaper works with geojson strings (character objects of class
geo_json
) and list
geojson objects of class
geo_list
. These classes are defined in the
geojsonio
package. It also works with Spatial
classes from the sp
package.
We will use the states
dataset from the
geojsonio
package and first turn it into a
geo_json
object:
library(geojsonio)
## Registered S3 method overwritten by 'geojsonsf':
## method from
## print.geojson geojson
##
## Attaching package: 'geojsonio'
## The following object is masked from 'package:base':
##
## pretty
library(rmapshaper)
## Registered S3 method overwritten by 'geojsonlint':
## method from
## print.location dplyr
library(sp)
<- geojson_json(states, geometry = "polygon", group = "group") states_json
## Assuming 'long' and 'lat' are longitude and latitude, respectively
For ease of illustration via plotting, we will convert to a
SpatialPolygonsDataFrame
:
<- geojson_sp(states_json)
states_sp
## Plot the original
plot(states_sp)
Now simplify using default parameters, then plot the simplified states
<- ms_simplify(states_sp)
states_simp plot(states_simp)
You can see that even at very high levels of simplification, the mapshaper simplification algorithm preserves the topology, including shared boundaries:
<- ms_simplify(states_sp, keep = 0.001)
states_very_simp plot(states_very_simp)
Compare this to the output using rgeos::gSimplify
, where
overlaps and gaps are evident:
library(rgeos)
## rgeos version: 0.5-9, (SVN revision 684)
## GEOS runtime version: 3.10.2-CAPI-1.16.0
## Please note that rgeos will be retired by the end of 2023,
## plan transition to sf functions using GEOS at your earliest convenience.
## GEOS using OverlayNG
## Linking to sp version: 1.4-7
## Polygon checking: TRUE
<- gSimplify(states_sp, tol = 1, topologyPreserve = TRUE)
states_gsimp plot(states_gsimp)
The package also works with sf
objects. This time we’ll
demonstrate the ms_innerlines
function:
library(sf)
## Linking to GEOS 3.10.2, GDAL 3.4.2, PROJ 8.2.1; sf_use_s2() is TRUE
<- st_as_sf(states_sp)
states_sf <- ms_innerlines(states_sf)
states_sf_innerlines plot(states_sf_innerlines)
All of the functions are quite fast with geo_json
character objects and geo_list
list objects. They are
slower with the Spatial
classes due to internal conversion
to/from json. If you are going to do multiple operations on large
Spatial
objects, it’s recommended to first convert to json
using geojson_list
or geojson_json
from the
geojsonio
package. All of the functions have the input
object as the first argument, and return the same class of object as the
input. As such, they can be chained together. For a totally contrived
example, using states_sp
as created above:
library(geojsonio)
library(rmapshaper)
library(sp)
library(magrittr)
## First convert 'states' dataframe from geojsonio pkg to json
<- geojson_json(states, lat = "lat", lon = "long", group = "group",
states_json geometry = "polygon")
%>%
states_json ms_erase(bbox = c(-107, 36, -101, 42)) %>% # Cut a big hole in the middle
ms_dissolve() %>% # Dissolve state borders
ms_simplify(keep_shapes = TRUE, explode = TRUE) %>% # Simplify polygon
geojson_sp() %>% # Convert to SpatialPolygonsDataFrame
plot(col = "blue") # plot
Sometimes if you are dealing with a very large spatial object in R,
rmapshaper
functions will take a very long time or not work
at all. As of version 0.4.0
, you can make use of the system
mapshaper
library if you have it installed. This will allow
you to work with very large spatial objects.
First make sure you have mapshaper installed:
check_sys_mapshaper()
## mapshaper version 0.5.88 is installed and on your PATH
## mapshaper-xl
## "/usr/local/bin/mapshaper-xl"
If you get an error, you will need to install mapshaper. First install node (https://nodejs.org/en/) and then install mapshaper in a command prompt with:
$ npm install -g mapshaper
Then you can use the sys
argument in any rmapshaper
function:
<- ms_simplify(states_sf, sys = TRUE)
states_simp_sys
plot(states_simp_sys[, "region"])