Zimlon

We wrote a brief description & process on how we generated a choropleth map at the county level using Matplotlib Basemap. The shapefile for US counties can be downloaded from census bureau website.  Shape files of multiple resolutions and years are available for download.

Our data for the visualization is a JSON dictionary with FIPS code of a counties as a key and home insurance value as mapped value.

We used the following code to map insurance values to a color, to be represented on the choropleth. The code just quantizes all the available insurance values to a finite set of colors and creates a new dictionary with county FIPS code as key and color as value. We are returning a single value between 0-255 because the final output we wanted is a choropleth of the single color.

import json

countydi = json.loads(open('insurancecosts.json').read())

insvals = map(lambda a:int(countydi[a]),countydi)

minins = min(insvals)

maxins = max(insvals)

colorlevels = 5

def calculate_color(countyval):

    level = ceil((countyval-minins)*colorlevels/(maxins-minins))

    color = 255-ceil(level*255/colorlevels)

    return color

county_color_dict = {}

for fips in countydi:

    color = calculate_color(int(countydi[fips]))

    county_color_dict[fips]=color

The shapefiles provided by the census bureau contain a few useful attributes which help in identifying the county. An example attribute dictionary of Barbour County, AL is given below.

{'NAME': 'Barbour', 'ALAND': 2291820706L, 'LSAD': '06', 'AWATER': 50864677, 'RINGNUM': 1, 'COUNTYFP': '005', 'SHAPENUM': 1, 'AFFGEOID': '0500000US01005', 'GEOID': '01005', 'STATEFP': '01', 'COUNTYNS': '00161528'}

So, apart from the FIPS code one can use a combination of county name and state FIPS codes to assign colors or any other feature of individual counties.  

The rest of the code to generate the visualization is given below. It basically does these things

  1. Creates a basemap to display US mainland,
  2. Reads the dbf files and assigns color to each county based upon its FIPS code
  3. Creates multiple patches each containing edges of counties which we want to represent in a single color
  4. Plots all those patches to show counties in appropriate color

import numpy as np

from mpl_toolkits.basemap import Basemap

import matplotlib.pyplot as plt

from matplotlib.patches import Polygon

from matplotlib.collections import PatchCollection

from math import ceil

patches = dict(map(lambda color:(color,[]),county_color_dict.values()))

fig, ax = plt.subplots()

mymap = Basemap(llcrnrlon=-129.098907,llcrnrlat=22.700324,urcrnrlon=-65.553985,urcrnrlat=52.177390,

             resolution='f', projection='merc', lat_0 = 37.697948, lon_0 = -97.314835)

mymap.drawmapboundary(fill_color='aqua')

mymap.fillcontinents(color='#ddaa66',lake_color='aqua')

mymap.drawcoastlines()

mymap.readshapefile('cb_2015_us_county_500k/cb_2015_us_county_500k', 'counties',drawbounds = False)

for info, shape in zip(mymap.counties_info, mymap.counties):

    try:

        color=county_color_dict[info['GEOID'].zfill(5)]

        patches[color].append( Polygon(np.array(shape), True) )

    except Exception as e:

        print e

for color in patches:

    htmlcolor = '#'+hex(int(color)).split('x')[1].zfill(2)+'0000'

    ax.add_collection(PatchCollection(patches[color],facecolor=htmlcolor , edgecolor='k', linewidths=1.0, zorder=2))

plt.savefig('/tmp/1.png')