If you're new into
Folium
, I strongly advise to read this introduction. It explains the basics: install the library, initialize a map, change tile, save as standalone html file, embed the map somewhere and so on.
Map initialization
Building a map with Folium
always start by initializing it. Pick the tile type you want, and select the location and zoom you're interested in. In this example, we're going to consider the whole world, centered on Europe.
# import the library
import folium
# Make an empty map
m = folium.Map(location=[20,0], tiles="OpenStreetMap", zoom_start=2)
# Show the map
m
The Data
A bubble map basically adds some markers (circles) at some locations on the map. Those circle must have coordinates (longitude and latitude). They usually have values as well, values that are mapped to the circle size.
Let's build a random dataset with Pandas
# Import the pandas library
import pandas as pd
# Make a data frame with dots to show on the map
data = pd.DataFrame({
'lon':[-58, 2, 145, 30.32, -4.03, -73.57, 36.82, -38.5],
'lat':[-34, 49, -38, 59.93, 5.33, 45.52, -1.29, -12.97],
'name':['Buenos Aires', 'Paris', 'melbourne', 'St Petersbourg', 'Abidjan', 'Montreal', 'Nairobi', 'Salvador'],
'value':[10, 12, 40, 70, 23, 43, 100, 43]
})
data
lon | lat | name | value | |
---|---|---|---|---|
0 | -58.00 | -34.00 | Buenos Aires | 10 |
1 | 2.00 | 49.00 | Paris | 12 |
2 | 145.00 | -38.00 | melbourne | 40 |
3 | 30.32 | 59.93 | St Petersbourg | 70 |
4 | -4.03 | 5.33 | Abidjan | 23 |
5 | -73.57 | 45.52 | Montreal | 43 |
6 | 36.82 | -1.29 | Nairobi | 100 |
7 | -38.50 | -12.97 | Salvador | 43 |
Add circles
Let's loop through this data frame and add one bubble to each location. Adding one circle is made thanks to the Circle()
function. It needs to be used together with the add_to()
function to be added to the map you're working on.
Note that the radius
parameter is set in meters. This is why it is multiplied by 20000
here, otherwise circles would be too small.
Mercator projection deforms the circles which are far away from the equator. To avoid this effect, radius
is multiplied by the cosine of the latitude.
Last but not least, the popup
parameters controls what's available in the popup you get when you click on a circle.
import math
# add marker one by one on the map, and account for Mercator deformation
for city in data.itertuples():
local_deformation = math.cos(city.lat * math.pi / 180)
folium.Circle(
location=[city.lat, city.lon],
popup='%s (%.1f)' % (city.name, city.value),
radius=city.value * 20000.0 * local_deformation,
color='crimson',
fill=True,
fill_color='crimson'
).add_to(m)
# Show the map again
m
Save the map as a standalone html file:
m.save('../../static/interactiveCharts/313-bubble-map-with-folium.html')
Zooming effect
In the example above, the circle radius is defined in meters. As a result, the circle becomes bigger on the screen when you zoom, and smaller when you unzoom.
It is possible to change this behaviour thanks to the CircleMarker()
function. In this case, the radius is defined in pixels. Which means circle will always appear the same, whatever the zoom level is.
n = folium.Map(location=[20,0], tiles="OpenStreetMap", zoom_start=3)
for city in data.itertuples():
folium.CircleMarker(
location=[city.lat, city.lon],
popup=city.name,
radius=float(city.value),
color='#69b3a2',
fill=True,
fill_color='#69b3a2'
).add_to(n)
# A title can be added to the map, if desired.
n.get_root().html.add_child(folium.Element("<h3 align='center'>Map with zooming circles</h3>"))
n