Plot choropleth maps with shapefiles using Geopandas | by Xiao Wang | Towards Data Science

Choropleth maps are useful and powerful visualisations which present data by areas or regions that colored or patterned according to the values. It is a bit like heatmaps but in geographic shapes.
I use it very often as it is really clear to users where the areas are and also handy for them to compare the data between areas with a quick look. If you are creating an interactive dashboard, choropleth maps will help readers slice and dice by areas as well as making the dashboard more vivid and not only limited to charts or tables.
My previous experience with choropleth maps was in Power BI where a large range of shapes have defaulted and there’s no flexibility to customize your own map. For example, when working on the crime data, I would like to display the data by police districts instead of cities or regions, which is not achievable by the Power BI shape map. The good thing is with Geopandas in Python, it is easy to achieve with a few lines.
Python packages:
import pandas as pdimport matplotlib.pyplot as plt #if using matplotlibimport plotly.express as px #if using plotlyimport geopandas as gpd
Shapefile:
The file for New Zealand police district was downloaded from Koordinates.
#set up the file path and read the shapefile datafp = "nz-police-district-boundaries.shx"map_df = gpd.read_file(fp)map_df.to_crs(pyproj.CRS.from_epsg(4326), inplace=True)#read the csv datadf = pd.read_csv('District.csv')
You may want to check and see what the shapefile looks like:
#see what the map looks likemap_df.plot(figsize=(20, 10))
As you may notice, there were some mismatch between the ‘District.csv’ and the ‘map_df’, for example the ‘Counties Manukau’ in the csv file and ‘Counties/Manukau’ in the map file. So we need to tidy those up before creating the maps:
#rename one of the columnsmap_df = map_df.rename({'DISTRICT_N': 'District'}, axis = 'columns')#drop a columnmap_df = map_df.drop(columns = 'DISTRICT_I')#replace the values in the dataframemap_df = map_df.replace(['Counties/Manukau','Northland'],['Counties Manukau','Northen'])
The last step before creating the choropleth map was to merge two dataset. This process is similar to SQL:
df_merged = map_df.merge(df, #map_df merge to df left_on=[‘District’],  right_on=[‘District’])
Then we get a new dataframe:
fig, ax = plt.subplots(1, figsize=(10,6))df_merged.plot(column='Sum', cmap='Blues', linewidth=1, ax=ax, edgecolor='0.9', legend = True)ax.axis('off')
fig = px.choropleth(merged, geojson=merged.geometry,                     locations=merged.index, color="Sum",                    height=500,                   color_continuous_scale="Viridis")fig.update_geos(fitbounds="locations", visible=True)fig.update_layout(    title_text='Map')fig.update(layout = dict(title=dict(x=0.5)))fig.update_layout(    margin={"r":0,"t":30,"l":10,"b":10},    coloraxis_colorbar={        'title':'Sum'})fig.show()
Choropleth maps have been used very often in dashboards nowadays. To create the maps, the first thing is to get the shapefile or geo json files you would like to apply in your personalised map and then merge your data accordingly.
Have a play with it 🤪! Any questions, feel free to drop me a line here or via my LinkedIn.