Python: how to create a choropleth map out of a shapefile of Canada?

天大地大妈咪最大 提交于 2019-12-04 23:12:25

This doesn't directly answer your question but hopefully solves your problem just the same. Have you looked at GeoPandas? It provides a simple API for working with and plotting shapefiles. You can replicate your code, including plotting a choropleth, in just a few lines:

import geopandas as gpd
canada = gpd.read_file('CAN_adm1.shp')
canada.plot('myvalues', cmap='OrRd')

This example assumes your shapefile has an attribute on each province that contains the values you want to plot, and the attribute is called "myvalues". If the values aren't stored in the shapefile, you can use canada.merge to merge your values map onto the GeoDataframe.

One caveat: At this time GeoPandas does not have an easy way to plot the legend for choropleth colors. (issue reported here)

Request: please rename your values dictionary to something else. That name has made writing this answer much more difficult. :)

Haven't tested this, but try:

color_numbers = values.values()
    # assumes the provinces are listed in the same order in values as 
    # they are in the shape file
for nshp in xrange(Nshp):
    ptchs   = []
    # ... code omitted ...
    the_facecolor = [(color_numbers[nshp]-1)/(Nshp-1), 0, 0];   #1..13 -> 0..1, then add G=B=0.
        # change the computation if the values in the values dictionary are no longer 1..13
    ax.add_collection(PatchCollection(ptchs, facecolor=the_facecolor, edgecolor='k', linewidths=.5))

The output you're getting has all blue patches, or [0,0,1]. Since that row isn't in cccol, I don't think cccol is the problem. Also, the code you added never actually references cccol after creating it! (Please add the link to the code sample you started from! :) )

Anyway, setting facecolor should help, as far as I know. Converting the values entry to the range 0..1, then making [R,G,B] color entries, should give you shades of red.

You mentioned confusion about cccol being a list of lists. It is list of RGBA tuples (red, green, blue, alpha transparency). These represent 13 "equally spaced" colors from orange to red.

In your case you don't want equally spaced colors but colors corresponding to myvalues. Do this:

cmap = matplotlib.cm.get_cmap('OrRd')
norm = matplotlib.colors.Normalize(min(myvalues.values()), max(myvalues.values()))
color_producer = matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)

Now color_producer has a method to_rgba that takes values from myvalues and converts them to the correct colors. The Normalize sets the min and max range of myvalues to the extreme colors of the Red-Orange colormap.

Now when you create each province's PatchCollection, you can set its facecolor to the RGBA tuple returned by color_producer:

# Change the province name passed as you iterate through provinces.
rgba = color_producer.to_rgba(myvalues['Manitoba'])
PatchCollection(ptchs, facecolor=rgba, edgecolor='k', linewidths=.5)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!