Updated On : Oct-06,2021 Tags geoplot, choropleth-maps
Geoplot - Choropleth Maps [Python]

Geoplot - Choropleth Maps [Python]

Geospatial data is generally available in datasets nowadays. The geospatial data can be names of locations (cities, states, countries, etc.) or it can be exact geolocations (longitude and latitude) as well. Visualizing geospatial data can give meaningful insights during data analysis.

The Choropleth map is one such representation of geospatial data. It can be used to analyze the distribution of data in geographical regions (e.g. population density, GDP per capita of countries, etc). Python has a list of libraries (geopandas, bokeh, cartopy, folium, ipyleaflet, etc.) that let us create choropleth maps. As a part of this tutorial, we'll introduce one new library named geoplot which is built on top of geopandas and cartopy. It let us create a choropleth map with just one line of code. We'll be using datasets from geopandas as well in our tutorial. As geoplot is built on top of geopandas and cartopy which itself are built on top of matplotlib, we can add details to charts using matplotlib as well.

If you don't have a background in geopandas and cartopy then please feel free to check our tutorials on them.

If you want to create scatter and bubble maps using geoplot then please check our other tutorial where we cover them.

We'll be creating choropleth maps using geoplot as a part of this tutorial. We'll try to explain the usage of geoplot API with simple examples.

We'll start by importing the necessary libraries. We have also printed the versions of the libraries that we are using.

In [1]:
import geoplot

print("Geoplot Version : {}".format(geoplot.__version__))

import matplotlib.pyplot as plt
Geoplot Version : 0.4.4

Below we have imported geopandas library which we'll be using for loading geospatial datasets. We have printed the version of the library and the list of datasets available through it.

In [2]:
import geopandas as gpd

print("Geopandas Version : {}".format(gpd.__version__))

print("Available Datasets : {}".format(gpd.datasets.available))
Geopandas Version : 0.9.0
Available Datasets : ['naturalearth_cities', 'naturalearth_lowres', 'nybb']

Below we have loaded the dataset with geospatial data about countries of the world. We can notice that geopandas dataframe has a column named geometry which holds information about the plotting shape of countries. We can merge this dataframe with other data frames and display other details for countries as well which we'll explain in our examples.

In [3]:
world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))

world.head()
Out[3]:
pop_est continent name iso_a3 gdp_md_est geometry
0 920938 Oceania Fiji FJI 8374.0 MULTIPOLYGON (((180.00000 -16.06713, 180.00000...
1 53950935 Africa Tanzania TZA 150600.0 POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...
2 603253 Africa W. Sahara ESH 906.5 POLYGON ((-8.66559 27.65643, -8.66512 27.58948...
3 35623680 North America Canada CAN 1674000.0 MULTIPOLYGON (((-122.84000 49.00000, -122.9742...
4 326625791 North America United States of America USA 18560000.0 MULTIPOLYGON (((-122.84000 49.00000, -120.0000...

Below we have loaded the world happiness dataframe. It has information like the happiness score of countries, GDP per capita, social support, life expectancy, generosity, freedom, and perception of corruption. We'll be merging this dataframe with geo dataframe from geopandas which we loaded earlier so that we can plot information from this dataset on the world map.

The happiness dataset can be downloaded from the below link.

In [4]:
import pandas as pd

happiness = pd.read_csv("datasets/world_happiness_2019.csv")

happiness.head()
Out[4]:
Overall rank Country or region Score GDP per capita Social support Healthy life expectancy Freedom to make life choices Generosity Perceptions of corruption
0 1 Finland 7.769 1.340 1.587 0.986 0.596 0.153 0.393
1 2 Denmark 7.600 1.383 1.573 0.996 0.592 0.252 0.410
2 3 Norway 7.554 1.488 1.582 1.028 0.603 0.271 0.341
3 4 Iceland 7.494 1.380 1.624 1.026 0.591 0.354 0.118
4 5 Netherlands 7.488 1.396 1.522 0.999 0.557 0.322 0.298

Below we have merged the geo dataframe which we loaded earlier with a happiness dataset based on the name of the countries. The final merged dataset will have columns from both datasets. We'll be using this dataset to create choropleth maps.

In [5]:
world_happiness = world.merge(happiness, left_on="name", right_on="Country or region")

world_happiness.head()
Out[5]:
pop_est continent name iso_a3 gdp_md_est geometry Overall rank Country or region Score GDP per capita Social support Healthy life expectancy Freedom to make life choices Generosity Perceptions of corruption
0 53950935 Africa Tanzania TZA 150600.0 POLYGON ((33.90371 -0.95000, 34.07262 -1.05982... 153 Tanzania 3.231 0.476 0.885 0.499 0.417 0.276 0.147
1 35623680 North America Canada CAN 1674000.0 MULTIPOLYGON (((-122.84000 49.00000, -122.9742... 9 Canada 7.278 1.365 1.505 1.039 0.584 0.285 0.308
2 326625791 North America United States of America USA 18560000.0 MULTIPOLYGON (((-122.84000 49.00000, -120.0000... 19 United States of America 6.892 1.433 1.457 0.874 0.454 0.280 0.128
3 18556698 Asia Kazakhstan KAZ 460700.0 POLYGON ((87.35997 49.21498, 86.59878 48.54918... 60 Kazakhstan 5.809 1.173 1.508 0.729 0.410 0.146 0.096
4 29748859 Asia Uzbekistan UZB 202300.0 POLYGON ((55.96819 41.30864, 55.92892 44.99586... 41 Uzbekistan 6.174 0.745 1.529 0.756 0.631 0.322 0.240

Simple World Map

If we want to create simple maps without any information presented through them then we can use polyplot() method available from geoplot.


  • polyplot(df,projection=None,extent=None,figsize=(8,6),ax=None,**kwargs) - This method takes as input GeoDataFrame and creates map from it. The GeoDataFrame is an data frame from geopandas which has column named geomtry holding information about geometries (polygons, multi-polygons, points, etc.).
    • The projection parameter takes as input instance of any projection available from geoplot.crs module. It can be used to change the projection of the map.
    • The extent parameter takes as input tuple of 4 values (min_longitude, min_latitude, max_longitude, max_latitude) specifying bounding box of map.
    • The figsize parameter accepts tuple specifying figure size.
    • The ax parameter accepts matplotlix Axes object.
    • All other extra parameters provided will be passed to polygons or multi-polygon objects which are present in geometry column. These parameters can be fill the color of polygons, edge color, edge width, etc.

Below we have created a world map by giving world GeoDataFrame which we loaded earlier using geopandas. We have asked the chart to fill the color of each country with lightgrey color.

In [ ]:
geoplot.polyplot(world, facecolor="lightgrey", figsize=(15, 8));

Geoplot - Choropleth Maps

Simple US Map

In this example, we have created a map of the US using polyplot() method. We have the first loaded dataset which has geospatial data of the US. We have loaded GeoJSON file as GeoDataFrame using geopandas. The link to the dataset is below.

We have then created the US map using GeoDataFrame. We have asked the method to fill polygons with dodgerblue color and the border color of the method is lightgrey. We have also used extent parameter specifying the bounding box of longitudes and latitudes for the US Map.

In [6]:
us_states_geo = gpd.read_file("datasets/us-states.json")

us_states_geo.head()
Out[6]:
id name geometry
0 AL Alabama POLYGON ((-87.35930 35.00118, -85.60667 34.984...
1 AK Alaska MULTIPOLYGON (((-131.60202 55.11798, -131.5691...
2 AZ Arizona POLYGON ((-109.04250 37.00026, -109.04798 31.3...
3 AR Arkansas POLYGON ((-94.47384 36.50186, -90.15254 36.496...
4 CA California POLYGON ((-123.23326 42.00619, -122.37885 42.0...
In [ ]:
geoplot.polyplot(us_states_geo,
                 facecolor="dodgerblue", edgecolor="lightgrey",
                 linewidth=2.,
                 extent=(-172,0, 10,75), figsize=(15, 8));

Geoplot - Choropleth Maps

Choropleth Maps

In this section, we'll introduce a method named choropleth() from geoplot which will let us create choropleth maps.


  • choropleth(df,projection=None,hue=None,cmap=None,norm=None,scheme=None,legend=None,legend_kwargs=None,legend_labels=None,legend_values=None,extent=None,figsize=(8,6),ax=None,kwargs) - This method takes as input GeoDataFrame as input and creates choropleth from it based on the value of parameter hue whose value will be used to color polygons of map.

    • The hue parameter takes as input string column name from GeoDataFrame or geo series, iterable specifying values to be used to color polygons of the map. We can give a column name from GeoDataFrame which has continuous data or categorical data. It'll create a color bar for a continuous column and a categorical legend for a categorical column.
    • The cmap parameter accepts matplotlib colormap name.
    • The scheme parameter accepts instances of mapclassify specifying scheme to group geo data. We can also give the string to this parameter specifying the name of any class from mapclassify. It'll create an instance of that class with default parameters. Below are some of the classification schemes for choropleth maps.
      • 'BoxPlot', 'EqualInterval', 'FisherJenks', 'FisherJenksSampled', 'HeadTailBreaks', 'JenksCaspall', 'JenksCaspallForced', 'JenksCaspallSampled', 'MaxP', 'MaximumBreaks', 'NaturalBreaks', 'Quantiles', 'Percentiles', 'StdMean'
    • The legend parameter accepts boolean value specifying whether to include a legend or not.
    • The legend_kwargs parameter accepts dictionary specifying options to modify the legend of the map.
    • The legend_labels accepts list of string values for categorical legends. We can group map values using scheme parameter into groups and using this parameter we can give labels for each group that will be included in the map.
    • The legend_values parameter accepts a list of values to be used for categorical legends.
    • The extent, ax, projection and \*\*kwargs parameters works like polyplot() method we explained above.

Continent Choropleth Map

Below we have created our first choropleth map which highlights each continent using a different color. We have used world GeoDataFrame which we have loaded earlier to create a map. We have give hue parameter with column named continent from GeoDataFrame which is categorical column. We have instructed the method to use Pastel2 colormap for our purpose.

In [ ]:
geoplot.choropleth(world, hue="continent", cmap="Pastel2", figsize=(15, 8), legend=True);

Geoplot - Choropleth Maps

World Happiness Choropleth Map

In this example, we have created a choropleth map using a continuous column of data. We have created a choropleth map showing the happiness scores of countries. We have used world happiness GeoDataFrame which we had created earlier by merging world GeoDataFrame with happiness pandas dataframe. We have instructed the method to use Score column of the dataframe to color polygons of the map. As Score is a continuous column, the map has created a color bar instead of showing categorical legend like the previous chart.

In [ ]:
geoplot.choropleth(world_happiness, hue="Score", cmap="Greens", figsize=(15,7), legend=True);

Geoplot - Choropleth Maps

World Healthy Life Expectancy Choropleth Map

In this example, we have created another choropleth map showing healthy life expectancy across world countries.

In [ ]:
geoplot.choropleth(world_happiness, hue="Healthy life expectancy", cmap="Blues", figsize=(15,7), legend=True);

Geoplot - Choropleth Maps

World Happiness Choropleth Map Categorical

In this example, we have explained how we can categorize the continuous column of GeoDataFrame. We have again created a choropleth map of the happiness score of countries but we have treated the happiness score column as categorical by using scheme parameter of choropleth() method. We have given it an instance of EqualInterval() with parameter k set to 8 which will divided values of happiness score columns into 8 equal clusters. We can notice in map legend the range of values covered in each cluster. This can be useful in a situation where we want to give a name to values that fall in particular ranges.

In [ ]:
import mapclassify

geoplot.choropleth(world_happiness,
                   hue="Score",
                   scheme=mapclassify.EqualInterval(world_happiness["Score"], k=8),
                   cmap="RdBu", edgecolor="white", linewidth=2.5,
                   figsize=(15,7), legend=True);

plt.title("Happiness Score Worldwide", fontdict={"fontsize": 15}, pad=5);

Geoplot - Choropleth Maps

Perception of Corruption Choropleth Map

In this section, we have created another choropleth map explaining how we can categorize continuous columns of data. This time we have created a choropleth map using the perception of corruption column of data. We have using Quantiles scheme to cluster values of perception of corruption columns into three clusters. We have given legend labels to three clusters as most corrupt, somewhat corrupt, and least corrupt. We have also given a dictionary to legend_kwargs parameter specifying how to modify the look of legend.

In [ ]:
import mapclassify


geoplot.choropleth(world_happiness,
                   hue="Perceptions of corruption",
                   scheme=mapclassify.Quantiles(world_happiness["Perceptions of corruption"], k=3),
                   cmap="RdYlGn", edgecolor="white",
                   legend_labels=["Most Corrupt", "Somewhat Corrupt", "Least Corrupt"],
                   legend_kwargs={"loc":"best",
                                  "fontsize": "large",
                                  "title":"Perception of Corruption",
                                  "title_fontsize":"large"},
                   figsize=(15,7), legend=True,
                  );

plt.title("Perception of Corruption Worldwide", fontdict={"fontsize": 15}, pad=5);

Geoplot - Choropleth Maps

US 2018 Population Choropleth Map

In this example, we'll be creating another choropleth map showing the US population in 2018 per us states. We have loaded the dataset which has information about states from the below link.

We have then merged us states GeoDataFrame with us population pandas dataframe to create merged dataframe which we'll use to create choropleth map.

In [23]:
us_state_pop = pd.read_csv("datasets/State Populations.csv")

us_state_pop.head()
Out[23]:
State 2018 Population
0 California 39776830
1 Texas 28704330
2 Florida 21312211
3 New York 19862512
4 Pennsylvania 12823989
In [24]:
us_states_pop = us_states_geo.merge(us_state_pop, left_on="name", right_on="State")

us_states_pop.head()
Out[24]:
id name geometry State 2018 Population
0 AL Alabama POLYGON ((-87.35930 35.00118, -85.60667 34.984... Alabama 4888949
1 AK Alaska MULTIPOLYGON (((-131.60202 55.11798, -131.5691... Alaska 738068
2 AZ Arizona POLYGON ((-109.04250 37.00026, -109.04798 31.3... Arizona 7123898
3 AR Arkansas POLYGON ((-94.47384 36.50186, -90.15254 36.496... Arkansas 3020327
4 CA California POLYGON ((-123.23326 42.00619, -122.37885 42.0... California 39776830

Below we have created a choropleth map of the US state’s population. The population column has continuous data and we have categorized it using Quantiles scheme into 4 clusters. The clusters represents population as least populated, somewhat populated, normally populated and densely populated. These let us analyze which states are most populated and which are least.

In [ ]:
import mapclassify

geoplot.choropleth(us_states_pop,
                   hue="2018 Population",
                   scheme=mapclassify.Quantiles(us_states_pop["2018 Population"], k=4),
                   cmap="RdYlBu", edgecolor="white",
                   extent=(-172,10, 10,75),
                   legend_labels=["Least Populated", "Somewhat Populated", "Normally Populated","Densely Populated"],
                   legend_kwargs={"loc":"best",
                                  "fontsize": "large",
                                  "title":"Population Density",
                                  "title_fontsize":"large"},
                   figsize=(16,8), legend=True);

plt.title("US 2018 Population", fontdict={"fontsize": 15}, pad=5);

Geoplot - Choropleth Maps



Sunny Solanki  Sunny Solanki