VOOZH about

URL: https://www.analyticsvidhya.com/blog/2021/09/how-to-visualise-data-in-maps-using-geopandas/

⇱ GeoPandas | How to Visualise data in Maps Using GeoPandas


India's Most Futuristic AI Conference Is Back – Bigger, Sharper, Bolder

  • d
  • :
  • h
  • :
  • m
  • :
  • s

How to Visualise data in Maps Using GeoPandas

Sreedevi Last Updated : 17 Oct, 2024
6 min read

This article was published as a part of the Data Science Blogathon

Introduction

More often than not, while performing an EDA, we are faced with a situation to display information with respect to geographical locations. For example, for a COVID 19 dataset, one may want to show the number of cases in various areas. Here is where the python library GeoPandas comes to our rescue.

This article attempts to give a gentle introduction to the usage of GeoPandas to visualize geospatial data effectively.

Geospatial data describe objects, events, or other features with respect to a location (coordinates) of the earth.
Spatial data is represented by the fundamental types of geometric objects (implemented by shapely)

πŸ‘ geospatia data
GeometryUsed to represent
PointsCentre point of plot locations etc.
LinesRoads, Streams
PolygonsBoundaries of buildings, lakes, states, etc.

CRS/Coordinate Reference System tells how (using a projection or a mathematical equation) a location (coordinates) on the round earth translates to the same location, on a flattened, 2-dimensional coordinate system (for example, your computer screens or a paper map). The most commonly used CRS is the β€œEPSG:4326”.

Now let’s get to the topic of our interest.

What is GeoPandas?

GeoPandas is based on the pandas. It extends pandas data types to include geometry columns and perform spatial operations. So, anyone familiar with pandas can easily adopt GeoPandas.

πŸ‘ Geo datastructure | Maps Using GeoPandas

 GeoPandas – GeoDataFrame & GeoSeries

The main data structure in GeoPandas is the GeoDataFrame that extends the pandas DataFrame. So all the base DataFrame operations can be performed on the GeoDataFrame. The GeoDataFrame contains one or more GeoSeries (that extends pandas Series) each of which contains geometries in a different projection (GeoSeries.crs). Though GeoDataFrame can have multiple GeoSeries columns, only one of these will be the active geometry i.e. all geometric operations will be on that column.

In the next sections, we will understand how to use some common functions like boundary, centroid, and most importantly plot method. To illustrate the working of geospatial visualizations, let’s will use the Teams data from the Olympics 2021 dataset.

Read the teams dataset before importing GeoPandas

The team’s dataset has the team name, discipline, NOC (country), and event columns. We will be using only the NOC and discipline columns in this exercise.

Python Code:

import pandas as pd
df_teams = pd.read_excel("Teams.xlsx")
print(df_teams.info())
print(df_teams.head())

Summarise the disciplines per each country and plot it.

df_teams_countries_disciplines = df_teams.groupby(by="NOC").agg({'Discipline':'count'}).reset_index().sort_values(by='Discipline', ascending=False)
ax = df_teams_countries_disciplines.plot.bar(x='NOC', xlabel = '', figsize=(20,8))
πŸ‘ df_teams_countries_disciplines - barplot
df_teams_countries_disciplines – barplot

Import GeoPandas and Read the Data

import geopandas as gpd

df_world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))

print(f"{type(df_world)}, {df_world.geometry.name}")

print(df_world.head())

print(df_world.geometry.geom_type.value_counts())
 

β€œnaturalearth_lowres” is a base map provided with geopandas which we loaded.

df_world is of type GeoDataFrame with continent, (country) name, and geometry (of country area) columns. geometry is of type GeoSeries and is the active geometry with country area represented in Polygon and MultiPolygon types.

Let’s now plot the world

df_world.plot(figsize=(10,6))
πŸ‘ df_world - plot
df_world – plot

Merge the teams and world dataset

df_world_teams = df_world.merge(df_teams_countries_disciplines, how="left", left_on=['name'], right_on=['NOC'])
print("Type of DataFrame : ", type(df_world_teams), df_world_teams.shape[0])
df_world_teams.head()
πŸ‘ merge dataframe

Note:

  • df_world_teams will have some entries with NOC and Discipline as NaN. This (merge on left instead of right) has been done intentionally so that we also have the countries that have not participated.
  • Few country names were inconsistent between the Olympics and world datasets. So I adjusted the country names (as far as possible). Details are in the source code.

Display a simple world map – plot boundary

As a first step, let’s plot the basic map – world with boundary only. In the next steps, we will colour the countries that we are interested in.

ax = df_world["geometry"].boundary.plot(figsize=(20,16))
πŸ‘ world map

Display a Choropleth map – plot  area

Next, let us colour the countries that have participated in the Olympics with the darkness of the colour based on the number of disciplines the country has participated in. The more disciplines the country participated in, the darker the shade and vice versa. Choropleth maps colour the regions/polygons in relation to a data variable.

df_world_teams.plot( column="Discipline", ax=ax, cmap='OrRd', 
 legend=True, legend_kwds={"label": "Participation", "orientation":"horizontal"})
ax.set_title("Countries Vs Number of Disciplines Particpated in 2021 Olympics")

where

  • ax is the axes on which to draw the map
  • cmap is the name of the colormap
  • legend & legend_kwds control the display of the legend.
πŸ‘ Countries that participated in Olympics
Countries that participated in Olympics

Based on the shading, we can quickly see that Japan, America, Italy, Germany, and Australia are the countries that have participated in most disciplines.

Notice that the legend at the bottom does not look that great. Let’s modify df_world_teams.plot to make the visualization more presentable.

fig, ax = plt.subplots(1, 1, figsize=(20, 16))
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="2%", pad="0.5%")
df_world_teams.plot(column="Discipline", ax=ax, cax=cax, cmap='OrRd',

legend=True, legend_kwds={"label": "Participation"})
πŸ‘ colormap

With a neat Colormap

Isn’t this visualization a lot neater?

Shading the countries that didn’t participate

plot missing_kwds

Now, what about the countries that didn’t participate? All the countries that are not shaded (i.e. in white colour) are the ones that did not participate. But let’s make that more obvious by shading these countries in grey. We can use missing_kwds with just a plain colour or with colour and pattern for that.

df_world_teams.plot(column="Discipline", ax=ax, cax=cax, cmap='OrRd',

legend=True, legend_kwds={"label": "Participation"},

missing_kwds={'color': 'lightgrey'})
πŸ‘ Countries not participated in Olympics - shaded grey | Maps Using GeoPandas
Countries not participated in Olympics – shaded grey
df_world_teams.plot(column= 'Discipline', ax=ax, cax=cax, cmap='OrRd', 
 legend=True, legend_kwds={"label": "Participation"}, 
 missing_kwds={"color": "lightgrey", "edgecolor": "white", "hatch": "|"})
πŸ‘ Countries not participated in Olympics - shaded grey & hatched | Maps Using GeoPandas
Countries not participated in Olympics – shaded grey & hatched

Mark the countries that participated in the least participated discipline – plot points

Which is the discipline where the participation was the least?

df_discipline_countries = df_teams.groupby(by='Discipline').agg({'NOC':'count'}).sort_values(by='NOC', ascending=False)
ax = df_discipline_countries.plot.bar(figsize=(8, 6))
πŸ‘ Disciplines Vs Number of Countries

Disciplines Vs Number of Countries

So Baseball/Softball is the discipline in which the least number of countries (12) participated. Now which countries participated in this discipline? Let’s find out.

For this, firstly create a dataset with only the countries that participated in the least participate discipline and then merge this dataset df_teams_least_participated_disciplines and df_world and then calculate the centroids.

# Create a dataset with only the countries participated in the least participate discipline

countries_in_least_participated_disciplines = df_discipline_countries[df_discipline_countries['NOC']<13].index.tolist()

print(least_participated_disciplines)

df_teams_least_participated_disciplines = df_teams[df_teams['Discipline'].isin(countries_in_least_participated_disciplines)].groupby(by=['NOC','Discipline']).agg({'Discipline':'count'})

df_teams_least_participated_disciplines.groupby(by=['NOC']).agg({'Discipline':'count'}).sort_values(by='Discipline', ascending=False)
# Merge 

df_teams_least_participated_disciplines with df_world
df_world_teams_least_participated_disciplines = df_world.merge(df_teams_least_participated_disciplines, how="right", left_on=['name'], right_on=['NOC'])
df_world_teams_least_participated_disciplines['centroid'] = df_world_teams_least_participated_disciplines.centroid
print("Type of DataFrame : ", type(df_world_teams_least_disciplines),df_world_teams_least_participated_disciplines.shape[0])
print(df_world_teams_least_participated_disciplines[:5])
πŸ‘ df_world teams | Maps Using GeoPandas

So Australia, Canada, Dominican Rep., and others have participated in the least-participated discipline.

Add the following lines to the plotting code we wrote earlier to mark these countries with a dark blue-filled circle.

df_world_teams_least_participated_disciplines["centroid"].plot(ax=ax, color="DarkBlue")

and the below to annotate the countries

df_world_teams_least_participated_disciplines.apply(lambda x: ax.annotate(text=x['name'], xy=(x['centroid'].coords[0][0],x['centroid'].coords[0][1]-5), ha='center'), axis=1)
πŸ‘ Countries participated in the Least Participated Disciplines | Maps Using GeoPandas
Countries participated in the Least Participated Disciplines

Now we have the Olympics teams displayed on the world map. We can extend this further to make it richer with information. A word of caution: Do not add too much detail to the map at the cost of clarity.

Summary

In the above sections, we have seen that geopandas.GeoDataFrame can work seamlessly with the base pandas.DataFrameβ€˜s functions – read_file, merge, etc., and with its own functions – boundary, centroid, plot, etc. to generate visualizations in a geographical map that enhances the data storytelling.

References: Source Code | GeoPandas | Spatial data | CRS

Image Sources

Image 1: https://www.earthdatascience.org/courses/earth-analytics/spatial-data-r/intro-to-coordinate-reference-systems/

The media shown in this article are not owned by Analytics Vidhya and are used at the Author’s discretion.

Login to continue reading and enjoy expert-curated content.

Free Courses

Generative AI - A Way of Life

Explore Generative AI for beginners: create text and images, use top AI tools, learn practical skills, and ethics.

Getting Started with Large Language Models

Master Large Language Models (LLMs) with this course, offering clear guidance in NLP and model training made simple.

Building LLM Applications using Prompt Engineering

This free course guides you on building LLM apps, mastering prompt engineering, and developing chatbots with enterprise data.

Improving Real World RAG Systems: Key Challenges & Practical Solutions

Explore practical solutions, advanced retrieval strategies, and agentic RAG systems to improve context, relevance, and accuracy in AI-driven applications.

Microsoft Excel: Formulas & Functions

Master MS Excel for data analysis with key formulas, functions, and LookUp tools in this comprehensive course.

Responses From Readers

Flagship Programs

GenAI Pinnacle Program| GenAI Pinnacle Plus Program| AI/ML BlackBelt Program| Agentic AI Pioneer Program

Free Courses

Generative AI| DeepSeek| OpenAI Agent SDK| LLM Applications using Prompt Engineering| DeepSeek from Scratch| Stability.AI| SSM & MAMBA| RAG Systems using LlamaIndex| Building LLMs for Code| Python| Microsoft Excel| Machine Learning| Deep Learning| Mastering Multimodal RAG| Introduction to Transformer Model| Bagging & Boosting| Loan Prediction| Time Series Forecasting| Tableau| Business Analytics| Vibe Coding in Windsurf| Model Deployment using FastAPI| Building Data Analyst AI Agent| Getting started with OpenAI o3-mini| Introduction to Transformers and Attention Mechanisms

Popular Categories

AI Agents| Generative AI| Prompt Engineering| Generative AI Application| News| Technical Guides| AI Tools| Interview Preparation| Research Papers| Success Stories| Quiz| Use Cases| Listicles

Generative AI Tools and Techniques

GANs| VAEs| Transformers| StyleGAN| Pix2Pix| Autoencoders| GPT| BERT| Word2Vec| LSTM| Attention Mechanisms| Diffusion Models| LLMs| SLMs| Encoder Decoder Models| Prompt Engineering| LangChain| LlamaIndex| RAG| Fine-tuning| LangChain AI Agent| Multimodal Models| RNNs| DCGAN| ProGAN| Text-to-Image Models| DDPM| Document Question Answering| Imagen| T5 (Text-to-Text Transfer Transformer)| Seq2seq Models| WaveNet| Attention Is All You Need (Transformer Architecture) | WindSurf| Cursor

Popular GenAI Models

Llama 4| Llama 3.1| GPT 4.5| GPT 4.1| GPT 4o| o3-mini| Sora| DeepSeek R1| DeepSeek V3| Janus Pro| Veo 2| Gemini 2.5 Pro| Gemini 2.0| Gemma 3| Claude Sonnet 3.7| Claude 3.5 Sonnet| Phi 4| Phi 3.5| Mistral Small 3.1| Mistral NeMo| Mistral-7b| Bedrock| Vertex AI| Qwen QwQ 32B| Qwen 2| Qwen 2.5 VL| Qwen Chat| Grok 3

AI Development Frameworks

n8n| LangChain| Agent SDK| A2A by Google| SmolAgents| LangGraph| CrewAI| Agno| LangFlow| AutoGen| LlamaIndex| Swarm| AutoGPT

Data Science Tools and Techniques

Python| R| SQL| Jupyter Notebooks| TensorFlow| Scikit-learn| PyTorch| Tableau| Apache Spark| Matplotlib| Seaborn| Pandas| Hadoop| Docker| Git| Keras| Apache Kafka| AWS| NLP| Random Forest| Computer Vision| Data Visualization| Data Exploration| Big Data| Common Machine Learning Algorithms| Machine Learning| Google Data Science Agent
πŸ‘ Av Logo White

Continue your learning for FREE

Forgot your password?
πŸ‘ Av Logo White

Enter OTP sent to

Edit

Wrong OTP.

Enter the OTP

Resend OTP

Resend OTP in 45s

πŸ‘ Popup Banner
πŸ‘ AI Popup Banner