Mapshaper is a javascript library for editing GIS data formats including GeoJSON, TopoJSON, Shapefiles and others. It's easier to install and can replace some of the functionality of ogr2ogr, allowing for integration into node-based workflows.
There's also an online gui at mapshaper.org you can use.
You can install mapshaper globally with npm
$ npm install -g mapshaper
If you're going to be using mapshaper in several different projects, however, I'd recommend installing locally on a per-project basis, and using npx
to run the commands. I'll be using the npx format here.
$ npm install mapshaper
Then you can run any subsequent commands with npx mapshaper ...
to use your local installation.
We'll use another command line program, curl
to download shapefiles for U.S. counties and Congressional Districts.
$ curl -O https://www2.census.gov/geo/tiger/GENZ2017/shp/cb_2017_us_cd115_500k.zip
$ curl -O https://www2.census.gov/geo/tiger/GENZ2016/shp/cb_2016_us_county_500k.zip
Then unzip them
$ unzip cb_2016_us_county_500k.zip
$ unzip cb_2017_us_cd115_500k.zip
Now we can use mapshaper to convert both of these shapes to geojson. The *
is a wildcard operator we can use to run the command on all files ending in .shp
at once:
$ npx mapshaper -i *.shp -o format=geojson
You can also filter fields from the data. In this case, instead of overwriting the json files, I'm going to create a new file indicating that this has been filtered in the filename.
When specifying fieldnames, make sure not to leave spaces between commas or it will throw an error.
# For the county layer
$ npx mapshaper -i cb_2016_us_county_500k.json \
-filter-fields STATEFP,COUNTYFP,GEOID,NAME \
-o us_counties_filtered.json format=geojson
# For congressional districts
$ npx mapshaper -i cb_2017_us_cd115_500k.json \
-filter-fields STATEFP,CD115FP,GEOID,CDSESSN \
-o congressional_districts_filtered.json format=geojson
You could also filter by a data field, for example, to get a geojson of California counties:
$ npx mapshaper -i us_counties_filtered.json \
-filter 'STATEFP == "06"' \
-o california_counties.json format=geojson
These shapefiles are big! To use them on a map we'll have to simplify. That's easy in mapshaper too. This time, to avoid overwriting data, we'll have to specify the input and output filenames.
# keep 10% of vertices in the output
$ npx mapshaper congressional_districts_filtered.json \
-simplify 10% \
-clean \
-o congressional_districts_simplified.json
$ npx mapshaper us_counties_filtered.json \
-simplify 10% \
-clean \
-o counties_simplified.json
You'll have to try different values to see what exactly will work. The Mapshaper GUI is a good way to test this.
You can reproject too, using either a projection string or a number of common aliases you can see by typing npx mapshaper -projections
.
Let's try converting to Albers USA.
$ npx mapshaper counties_simplified.json -proj albersusa -o us_counties_albers.json
We can also convert the California file we created into California Albers
$ npx mapshaper california_counties.json -proj +init=EPSG:3310 -o california_counties_projected.json
One thing I like to do is create state shapes by dissolving the county shapes together, this makes sure our states have consistent borders with the counties.
$ npx mapshaper us_counties_albers.json \
-dissolve STATEFP -o states_albers.json
You can then convert your end result into an SVG and import into Illustrator.
$ npx mapshaper us_counties_albers.json -o us_counties_albers.svg
So what else can you do with this? I like to arrange data processing steps into make
files, allowing me to set file inputs and outputs separately. This command, for example, takes three shapefiles and combines them into one topojson file. You could call this with make project-files/topojson/districts-merged.topojson
# files after the colon are the input files used in the command
topojson/merged_districts.topojson: cb_2017_us_cd115_500k.shp \
cb_2016_us_county_500k.shp
# Make the output directory if it doesn't exist
@mkdir -p $(dir $@)
@rm -f $@
# ^i is a variable representing the input files,
# $@ represents the output file
npx mapshaper \
-i $^ combine-files snap \
-o $@ format=topojson
This is only the barest bones of what you can do with Mapshaper. Creator Matt Bloch has detailed many more examples here.