Letâs say youâre working with real-world data. And in that data youâve got the latitudes and longitudes of some entities. And more than that, you want to put those entities on a map and show it off to your friends. How would you do it?
Well, youâve got a few optionsâŠ
- Manually place points on a map using Google Maps, which is kinda okay when you have 2 or 3 entities but once you go over 10 it gets a little tedious right?!
- Use a library/package from some programming language that does it for you. Personally my favorite option đđ»
There are a few libraries out there for this, but today weâre going to talk about Folium.
Folium
The purpose of this library is to combine Pythonâs data manipulation power with the map visualization strength of the JavaScript library Leaflet. The idea here is to make it even easier to plot points on a map.
Whereâs the code?
All the code Iâm going to show below is neatly organized in this GitHub repo. It has the environment setup instructions both with docker and without docker.
Installation
Start by setting up the environment:
$ git clone https://github.com/jtemporal/intro-folium.git
$ cd intro-folium/
With docker
If you like the đł:
$ docker-compose build
Without docker
If youâre not into the đł:
$ pip install -r requirements.txt
$ pip install jupyter
Getting started
After that, still in the terminal:
With đł:
$ docker-compose up jupy
or without docker:
$ jupyter notebook
Once you run one of the commands above, youâll see a message like this one in your terminal:

The last line shows the access token, just copy it and paste it in your browser to open jupyter. Something like this should show up for you:

If you run the folium_intro.ipynb notebook end to end, youâll get the same results Iâm going to show here. Also, if you click on the map images that follow, youâll be taken to those mapsâ pages so you can interact with them đ
Hands on

We start by importing the necessary libraries and creating a map:
import pandas as pd
import folium
brasil = folium.Map(
location=[-16.1237611, -59.9219642], # Coordinates pulled from Google Maps
zoom_start=4
)
folium.Map() only needs the location parameter to create your map. This parameter takes a latitude-longitude pair that can be a list or a tuple. Here I also passed a value (4) for the zoom_start parameter. The default of this parameter is 10, but a zoom of 10 doesnât keep the whole country in view, so, the new value of 4. When we call the map, we get:
brasil
But now I want to add pins to the map. Here Iâll use as an example a dataset with the geolocations of companies that showed up in the expense reports analyzed by Operação Serenata de Amor. In the intro-folium repo thereâs a reduced version of this dataset. So letâs start by reading the data and adding the first two companies to the map:
empresas = pd.read_csv('empresas.xz')
empresa1 = empresas.iloc[0]
folium.Marker(
location=[empresa1['latitude'], empresa1['longitude']],
).add_to(brasil)
empresa2 = empresas.iloc[1]
folium.Marker(
location=[empresa2['latitude'], empresa2['longitude']],
).add_to(brasil)
folium.Marker() places a location âpinâ on the map. For that to work we need to pass in location again and also indicate which map to add the pin to using the add_to() method. Calling the map again, we get:
brasil
Resist the curiosity of putting all the companies on a map. With more than fifty thousand companies in this dataset, itâll probably crash your computer (it crashed my jupyter). Trust me, a map with all the companies in the dataset looks like this:

Knowing that showing off the beauty above crashes your computer, letâs just pick one state to show:
empresas_pe = empresas[empresas['state'] == 'PE']
To improve the visualization I also started a new map, this one with the coordinates of Pernambuco state (my home state â€ïž), see:
pernambuco = folium.Map(
location=[-8.3833569, -38.5757127],
zoom_start=7
)
pernambuco
And putting the companies on the map:
for _, empresa in empresas_pe.iterrows():
folium.Marker(
location=[empresa['latitude'], empresa['longitude']],
).add_to(pernambuco)
pernambuco
Here we can already notice something worth analyzing: even though the dataset shows them registered as Pernambuco, we find two companies whose latitude and longitude arenât within the state boundaries đ€
Cool, but a little bland right? So letâs take a look at how to color things up a bit?
Letâs start by reducing our number of companies even more. I picked the 110 companies from Olinda â€ïž, and put them on the map:
empresas_olinda_pe = empresas[empresas['city'] == 'OLINDA']
olinda = folium.Map(
location=[-7.9981267, -34.9082027],
zoom_start=13
)
for _, empresa in empresas_olinda_pe.iterrows():
folium.Marker(
location=[empresa['latitude'], empresa['longitude']],
).add_to(olinda)
olinda
Then I picked some of the 22 neighborhoods with companies to color, creating a dictionary that maps a neighborhood name to a color:
colors = {
'AMPARO': 'pink',
'GUADALUPE': 'blue',
'CASA CAIADA': 'green',
'PEIXINHOS': 'orange',
'RIO DOCE': 'red',
'BAIRRO NOVO': 'purple',
}
olinda = folium.Map(
location=[-7.9981267, -34.9082027],
zoom_start=13
)
for _, empresa in empresas_olinda_pe.iterrows():
if empresa['neighborhood'] in colors.keys():
folium.Marker(
location=[empresa['latitude'], empresa['longitude']],
icon=folium.Icon(color=colors[empresa['neighborhood']])
).add_to(olinda)
Here we used a new parameter of folium.Marker(), the icon, which takes a folium.Icon object and thus the coloring we want. Note that, before putting the points on the map, I clear the Olinda map by recreating the object so I donât end up putting colored pins on top of the old map with the blue pins. One more detail: this type of marker (that looks like a đ) follows the bootstrap colors, so itâs limited, but for this example it works:
olinda
Three little extras
Maps on web pages
You can save your maps as HTML pages using the command below. Just identify the map you want to save, use the .save() method and pass a filename as a parameter. All the map pages in this post were generated this way:
olinda.save('mapas_htmls/olinda_some_colored.html')
Extra info on a map
You can also pass information about the entity youâre placing on the map using the popup parameter. This way, when you click on one of the pins, a balloon shows some info:
folium.Marker(
location=[empresa['latitude'], empresa['longitude']],
popup='I am a company from Olinda',
icon=folium.Icon(color=colors[empresa['neighborhood']])
).add_to(olinda)

A rainbow
As I said before, folium.Marker() has limited colors, so if you need more colors, or if you need different colors from the ones available, use either folium.CircleMarker() or folium.PolygonMarker(). Both accept color hashes.
So, are you going to make some maps too? đ
Fun facts and tips
Open maps (and data)
Leaflet, and by consequence Folium too, uses OpenStreetMap to build its maps. OpenStreetMap maps are open and built by a community of people interested in maintaining and helping the project. For example, if you find any errors somewhere on the map you can submit corrections. I recommend taking a peek at the OpenStreetMap Wiki for more info.
df.iloc[i]
A way to view any row of the dataframe as a nicely formatted print, just pass the row index as i.
df.iterrows()
Very useful for iterating through the rows of a dataframe one by one. This method always returns an index and the corresponding row.
Links
- A summary of pandas tips: LelĂȘ Portellaâs Pandas cheatsheet
- WebApp to help pick a color set: ColorBrewer2 (thanks Geremia đ)
- What to do when you have too many points? Filipeâs tip (thanks đ) was to use a folium plugin called
MarkerCluster






