Last time, we were able to create a map through Python and Matplotlib with our shapefile consisting of all of the NC voting districts. This time, we want to map it, but give each shape a different color.
This can be accomplished by providing the facecolor variable when we add our voting district shapefile patch collection with an array parameter instead of the 'green' that we provided it last time.
Eventually, we want to specify a color by the chosen voting district. That'll be for next time. This time, we'll just create an array of random colors.
I do know that we'll have thirteen voting districts. I'm going to create a dictionary consisting of each voting district number and a corresponding color:
color_switch = {0: 'teal', 1:'red',2:'blue',3:'green',4:'purple',5:'brown',6:'orange',7:'white',8:'black',9:'tan',10:'lightblue',11:'pink',12:'yellow'}
From there, build a list by looping through the number of voting districts, selecting one of those items, and appending it to that list we'll eventually use to color the shapes. to select something at random, we'll use the aptly named random module.
import random
color_choice = [] #list for our colors
#for each shape in our shapefile, pick a random color and append to our color choice list.
for shape in shapes: color_choice.append(random.choice(color_switch))
And then apply the list as an array (thanks to numpy) when we add the collection to the map.
import numpy as np
ax.add_collection(PatchCollection(patches, facecolor= np.array(color_choice), edgecolor='k', linewidths=0.2, zorder=2))
And you get a map like so!
Here's all the code to create the map from the beginning:
import matplotlib.pyplot as plt #what I need to plot stuff to my map.
from mpl_toolkits.basemap import Basemap #what I need to create my basemap.
import shapefile #what I need to read the shapefile from the NC SBE.
from pyproj import Proj #module used to change our projection from the nc to the traditional
from matplotlib.patches import Polygon #used to convert our newly reprojected coordinates to a polygon/patch shape that matplotlib can plot.
from matplotlib.collections import PatchCollection #we'll be adding all of our voting districts to a patch collection and then plotting that collection.
import numpy as np #allows us to better interact with arrays, which is the structure used with polygons/ patches.
import random #use this to select a random color from our voting district color dictionary.
conv_coords = list() #hold our converted coordinates here as we apply each set of converted coordinates that make up our shape.
patches = [] #list/collection we'll be sticking our patches/polygons/voting districts into. This'll pass as the points within our point collection.
#projection type for the voting districts.
nc = Proj("+proj=lcc +lat_1=34.33333333333334 +lat_2=36.16666666666666 +lat_0=33.75 +lon_0=-79 +x_0=609601.2192024384 +y_0=0 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs ", preserve_units=True)
vote = shapefile.Reader('ncsbe\\Precincts.shp') #creates an instance that has the lists of data we want.
shapes = vote.shapes() #lists of coordinates making up the shape for each voting district.
for x in range(0,len(shapes)): #for each voting district...
conv_coords.append([]) #apply a new list to our main list consisting of all the shapes.
for y in range(0,len(shapes[x].points)): #for each set of coords in the shape...
lon, lat = nc(shapes[x].points[y][0], shapes[x].points[y][1], inverse=True) #convert the shape file points into traditional lat/long coords.
conv_coords[x].append([lon,lat]) #write the converted coordinates to the new sublist.
patches.append(Polygon(np.array(conv_coords[x]), True)) #sublist consisting of all the shapes coordinates is complete. append to patchcollection list.
#dictionary that associates a voting district to a color.
color_switch = {0: 'teal', 1:'red',2:'blue',3:'green',4:'purple',5:'brown',6:'orange',7:'white',8:'black',9:'tan',10:'lightblue',11:'pink',12:'yellow'}
color_choice = [] #list to hold our color selections.
#for each shape in our voting district shapefile.
for shape in shapes: color_choice.append(random.choice(color_switch))
#create our basemap.
m = Basemap(projection= 'cyl', lon_0 = -80, lat_0 = 35, llcrnrlon=-84.9,llcrnrlat=33.5,urcrnrlon=-75.,urcrnrlat=36.6, resolution='i')
#create a figure/subplot that'll be our canvas for the voting districts. plt is the main plot object.
fig = plt.figure(figsize=(20,6)) #provide a parameter for figsize to make a wide canvas (NC's long shape).
ax = fig.add_subplot(111)
#add the general stuff we want on our map that comes with basemap.
m.drawcountries(linewidth=0.5)
m.drawcoastlines(linewidth=0.5)
m.drawstates(linewidth=0.5)
#and with that subplot, apply our patch collection (all of our voting district shapes.
ax.add_collection(PatchCollection(patches, facecolor= np.array(color_choice), edgecolor='k', linewidths=0.2, zorder=2))
#create a file with our basemap and plot overlay.
plt.savefig('vote_map_test_colors.png',dpi=600, alpha=True)
#and complete.
plt.close()