Maps in python and d3

Sometimes we want to draw maps.  The census bureau has shape files for the different states located here.  There are a lot of additional resources and documentation available here.  There are a lot of ways to use these files.  You can load them into geopandas, fiona, pyshp, osgeo, or a ton of other programs.  Here’s a way to load a shape file into geopandas and pull out two states:

import geopandas as gpd
states = gpd.read_file('cb_2016_us_state_500k/cb_2016_us_state_500k.shp')
just_md_va = states[states.STUSPS.isin(['MD', 'VA'])]
just_md_va.to_file('just_md_va.shp', driver='ESRI Shapefile')

If you want to use maps in d3, then there’s a great resource called TopoJSON, an extension of GeoJSON.  They have a repository of maps here. “TopoJSON is an extension of GeoJSON that encodes topology. Rather than representing geometries discretely, geometries in TopoJSON files are stitched together from shared line segments called arcs.”  This code will draw the outline of the US with county lines:

https://bl.ocks.org/mbostock/4108203

<svg width="960" height="600" fill="none" stroke="#000" stroke-linejoin="round" stroke-linecap="round"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script>

var svg = d3.select("svg");

var path = d3.geoPath();

d3.json("https://unpkg.com/us-atlas@1/us/10m.json", function(error, us) {
  if (error) throw error;

  svg.append("path")
      .attr("stroke", "#aaa")
      .attr("stroke-width", 0.5)
      .attr("d", path(topojson.mesh(us, us.objects.counties, function(a, b) { return a !== b && (a.id / 1000 | 0) === (b.id / 1000 | 0); })));

  svg.append("path")
      .attr("stroke-width", 0.5)
      .attr("d", path(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; })));

  svg.append("path")
      .attr("d", path(topojson.feature(us, us.objects.nation)));
});

</script>

Leave a comment