How to create bubble maps in Python with Geospatial data
Tags: Python, Geographicdatascience, Data Science, Geopandas, Data Visualization

We often use Choropleth maps to display areas, and in that case, we use a colour encoding. Choropleth maps have an inherent bias problem with large areas. In contrast, bubble maps use circles to represent a numeric value of an area or region.

It often seems to be complicated and a bit advanced feature to create your bubble map in Python, but it is not. It is like creating bubble charts with latitude and longitude columns. Let us first import the libraries we need.

import pandas as pd

import numpy as np import geopandas as gpd import matplotlib.pyplot as plt

import plotly_express as px

And we can read the data with Geopandas. With Geopandas, you can read most of the geographic data formats like Shapefile, Geojson, Geo package, etc.. In this example, we are using population data from the city of Mälmo, Sweden.

gdf = gpd.read_file(“data/malmo-pop.shp”)

gdf.head()

Here is a glimpse of the first rows of the dataset. We have numerous columns of the population subdivision (Age 5 to age 80 and above) for each administrative unit (Deso).

We usually use choropleth maps and use a colour encoding. As we are going to see, we can create a choropleth map very easily with Geopandas. Notice that we first normalize the data (Age80_w) by subdividing the total population.

gdf["Age_80_norm"] = (gdf["Age80_w"] / gdf["Total"]) * 100 fig, ax = plt.subplots(figsize=(16,16))

gdf.plot(ax=ax, column="Age_80_norm", cmap="Blues",edgecolor="grey", linewidth=0.4, legend=True)

ax.axis("off")

plt.axis('equal')

plt.show()

Bubble Maps

Alternatively, we can use bubble maps and avoid some of the pitfalls of choropleth maps. For example, we do not need to normalize the data, and we can use the total subdivision of populations. However, we need to do some conversion to the data to be able to create a bubble map.

As you can see, the data we are using are Polygons, and we need points if we want to create bubble maps. That is, however, a simple process with Geopandas. We only need to change the geometry column, in this case, Polygons to Point geometry.

gdf_points = gdf.copy()

gdf_points[‘geometry’] = gdf_points[‘geometry’].centroid

We first copy the Geodataframe with Polygon geometry to a new Geodataframe. As we want to the bubble to be at the centre of the area, we can use centroid function in Geopandas to achieve this.

Now, we have the same Geodataframe with different Geometry column, a Point Geometry. Let us plot a bubble map as we have points dataset now.

fig, ax = plt.subplots(figsize=(16,16))

gdf.plot(ax=ax, color=”lightgray”, edgecolor=”grey”, linewidth=0.4)

gdf_points.plot(ax=ax,color=”#07424A”, markersize=”Age80_w”,alpha=0.7, categorical=False, legend=True ) ax.axis(“off”)

plt.axis(‘equal’)

plt.show()

The map below shows a bubble map for Age 80 and above population in a smaller administrative area in Mälmo, Sweden. Each circle represents a different size based on the subtotal population at the age of 80 and above. To construct a bubble map, you need to provide markersize to the column you want to be mapped, and in this case, the Age80_w.

As you can see, this is a static map, and often a problem with bubble maps is the overlapping of point circles. One way we can avoid this is to create interactive maps that allow the user to interact with and zoom into an area of interest. In the next section, we are going to see how you can create an interactive bubble map.

Interactive Bubble Maps

There are different Python libraries for plotting interactive bubble maps. To construct an interactive bubble map, we use Plotly Express. We just need to convert to another projection to display the map with Plotly Express. Plotly Express has scatter_mapbox() function which can take a Geodataframe and the column you want to use for the bubble map.

gdf_points_4326 = gdf_points.to_crs(“EPSG:4326”) fig = px.scatter_mapbox(

gdf_points_4326,

lat=gdf_points_4326.geometry.y,

lon=gdf_points_4326.geometry.x,

size=”Age80_w”,

color=”Total”,

hover_name = “Age80_w”,

color_continuous_scale=px.colors.colorbrewer.Reds,

size_max=15,

zoom=10

)

fig.show()

With Plotly Express, we can avoid the overlapping problem of bubble maps by creating an interactive bubble map. See the below GIF.

Bubble maps can be an alternative map to display a numeric variable with different bubble size, instead of the most used choropleth maps. If you have a list of regions (i.e. administration areas) with values (i.e., age subdivisions), bubble maps can replace Choropleth maps. Bubble maps do not have the inherent big area bias in choropleth maps.

Conclusion

In this tutorial, we have seen how to create both static and interactive bubble maps, using Python. The static bubble maps have an overlapping problem. To avoid it, you can either create interactive maps that allow zoom in/out or increase the transparency of the static map circles.

The code for this tutorial is available in this Github Repository.