An Introductory Guide to Folium
Folium
Folium is a powerful Python library that allows us to manipulate geospatial data and visualize it on a leaflet map making our visualizations interactive.
Note: Leaflet is a leading open-source JavaScript library for plotting interactive maps.
This way, Folium has the flexibility of python and the strength of leaflet.js
library. This quality makes Folium easy to use and efficient to create dashboards.
Installing and Importing Folium
Folium is pre installed on Google Colab as well Kaggle, but you can use the following pip command to install folium locally.
!pip install folium --quiet
import folium
Latitude and Longitude
Folium accepts geographical coordinates in the form latitude, longitude which become the pivots of our maps.
Latitude and Longitudes are angles that uniquely define the points in a sphere.
A LATITUDE ranges from top and bottom. We ususally follow the Gemoetric Sign convention i.e above and below .
Simillarly, a LONGITUDE ranges from left and right. Again, we follow the Gemoetric Sign convention i.e from to right, and from to left.
FunFact: The Null Island
Creating your first interactive Map
To create a basic interractive map, folium provides a simple method called folium.Map
which takes the coordinates of our base location in the location
argument.
Additionally, we can set the zoom level using the argument zoom_start
. Higher the value inserted in zoom_start
, higher the zoom in level. Below, I have created a simple map with the location coordinates of San Jose, Costa Rica.
map = folium.Map(location=[9.9281, -84.0907], zoom_start=13)
map
Saving a Folium Map
By default, folium creates a map in seperate HTML file. We can save them using .save
. This allows us to view our map on an HTML page.
map.save("SanJose.html")
Tile Styles in Folium
Folium offers different styles to generate our maps. Each style is a different tileset made up of vector data.
A vector tile is a lightweight data format for storing geospatial vector data, such as points, lines, and polygons.
The following tilesets are available with Folium:
- OpenStreetMap
- Mapbox Bright
- Mapbox Control Room
- Stamen (incl. Terrain, Toner, and Watercolor)
- Cloudmade
- Mapbox
- CartoDB (incl. positron and dark_matter)
Each of these styles showcase different features of a map hence can be used for different purposes.
In case no tiles
is specified, folium provides the OpenStreetMap
view by default.
Below we have plotted a Topographic map of San Jose and other parts of Costa Rica using Stamen Terrain
. This shows large-scale detail and quantitative representation of relief features with the help of contour lines etc.
map = folium.Map(location=[9.9281, -84.0907], zoom_start=10, tiles='Stamen Terrain')
map
Because each tileset is a different layer and provides different information, we can add each layer to the same map using the .add_to
function.
map = folium.Map(location=[9.9281, -84.0907], zoom_start=10, tiles='Stamen Terrain')
folium.TileLayer('Stamen Terrain').add_to(map)
folium.TileLayer('Stamen Toner').add_to(map)
folium.TileLayer('Stamen Water Color').add_to(map)
folium.TileLayer('cartodbpositron').add_to(map)
folium.TileLayer('cartodbdark_matter').add_to(map)
folium.LayerControl().add_to(map)
map
You can control or change the map tile from the top right corner of your map.
Adding Markers to your Folium Maps
From the oldest map ever drawn, Markers have been an essential part of cartography. These help to indicate the type of destination or the destination itself.
Folium allows us to create markers in two simple steps:
-
First we use the
folium.Marker()
class to declare a marker. We can also add argumentspopup
andtootip
to control what we see when hovering over them. -
Next we can simply add these markers to our base
map
using the function.add_child(map)
.
map = folium.Map(location=[9.9281, -84.0907], zoom_start=9)
folium.Marker(
[10.204899282955244, -84.16153139999999],
popup="<i>La Paz Waterfall Gardens Nature Park, Costa Rica</i>").add_to(map)
folium.Marker(
[10.441940811102523, -84.66740968917554],
popup="<b>La Fortuna Waterfall, Costa Rica</b>").add_to(map)
map
The difference between tooltip and popup is that the content visible over a marker when we hover over it is called TOOLTIP, whereas the content visible over a marker when we click it is called POPUP.
Changing Marker Icons and colors
Folium offers ways to mark your map with markers of variable icons and colors to indicate different localities.
You can find the full list of icons and color's supported by folium here: https://getbootstrap.com/docs/3.3/components/
map = folium.Map(location=[9.9281, -84.0907], tiles='Stamen Terrain', zoom_start=10)
folium.Marker(
[10.204899282955244, -84.16153139999999],
popup="<i>La Paz Waterfall Gardens Nature Park, Costa Rica</i>",
icon=folium.Icon(color='green',icon="glyphicon glyphicon-tree-deciduous" )
).add_to(map)
folium.Marker(
[10.441940811102523, -84.66740968917554],
popup="<b>La Fortuna Waterfall, Alajuela Province, La Fortuna, Costa Rica</b>",
icon=folium.Icon(color='green',icon="glyphicon glyphicon-tree-deciduous" )
).add_to(map)
map
Adding Explicit Markers While Interacting
Another feature within folium is that we can explicitly add a marker to our map. It can be done using a simple function ClickForMarker()
, and .add_child()
.
Let's look at it below. You should be able to drop markers with a simple click.
from folium.map import Icon
map = folium.Map(location=[9.9281, -84.0907], zoom_start=9)
folium.Marker(
[10.204899282955244, -84.16153139999999],
popup="<i>La Paz Waterfall Gardens Nature Park, Costa Rica</i>",
icon=folium.Icon(color='green')
).add_to(map)
folium.Marker(
[10.441940811102523, -84.66740968917554],
popup="<b>La Fortuna Waterfall, Alajuela Province, La Fortuna, Costa Rica</b>",
icon=folium.Icon(color='green')).add_to(map)
map.add_child(folium.ClickForMarker(popup="NewMarker"))
map
Drawing Shapes
Another feature to make your map results more precise are highlighting an area with the help of shapes. Below is an example where I've used folium.Circle
, added arguments like radius, color, etc... & added it to my base map.
map = folium.Map(location=[9.9281, -84.0907], zoom_start=10)
folium.Circle(
radius=500,
location = [10.202164194235301, -84.23876102272602],
popup = "Poás Volcano",
color = 'red',
fill = True
).add_to(map)
folium.CircleMarker(
location=[9.9281, -84.0907],
radius = 50,
popup = 'SanJose',
color = "green",
fill = False
).add_to(map)
map
The size of your marker remains intact even if your zoom in or out on your map. You can explore a whole other bunch of different shapes you can highlight on a map.
GeoJSON and TopoJSON Overlays
A point on a map mostly consists of latitude and longitude, but sometimes you can add other physical factors on a map like a path or a boundary. For this we use GeoJSON & TopoJSON formats.
GeoJSON is an open standard format for encoding a variety of geographic data structures.
This helps to represent different geospatial features using JSON.
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}
TopoJSON on the side is an extension of GeoJSON files that encodes the Topology of a certain space. This format contains both geospatial data (arcs) and attribute data.
We can pass GeoJSON and TopoJSON layers as an overlay, and multiple layers can be visualized on the map. To plot a map with GeoJSON and TopoJSON data structures Folium has two methods:
folium.GeoJson
&folium.TopoJson
.
Let's implement them.
Dataset: Since there was not a lot of data representing Indian states online, I've used local data. I've uploaded the dataset on kaggle: https://www.kaggle.com/datasets/himanigulati/topo-choro-json-files. You can download it and manually upload it to your jupyter notebook.
import json
f = open('/content/IndiaStates_topo.json')
india_dist = json.load(f)
v = open('/content/IndiaStates_topo.json')
india_states_topo = json.load(v)
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
/tmp/ipykernel_39/3209328809.py in <module>
1 import json
2
----> 3 f = open('/content/IndiaStates_topo.json')
4 india_dist = json.load(f)
5
FileNotFoundError: [Errno 2] No such file or directory: '/content/IndiaStates_topo.json'
map = folium.Map(location=[22, 78],
zoom_start=4,
tiles = 'cartodbpositron')
#folium.GeoJson(india_dist, name="geojson").add_to(map)
folium.TopoJson(india_states_topo, 'objects.India_States_2020_compressed', name="topojson").add_to(map)
map
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/tmp/ipykernel_39/2846193947.py in <module>
5 #folium.GeoJson(india_dist, name="geojson").add_to(map)
6
----> 7 folium.TopoJson(india_states_topo, 'objects.India_States_2020_compressed', name="topojson").add_to(map)
8
9 map
NameError: name 'india_states_topo' is not defined
Additional Map for River Centerlines:
Follwing GeoJSON Data represents, Rivers and Lakes Centerlines on a map made around the null point. You can find the data here: https://d2ad6b4ur7yvpq.cloudfront.net/
river_url = "https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_rivers_lake_centerlines.geojson"
map = folium.Map(location=[0, 0], tiles='Stamen Watercolor', zoom_start=2)
folium.GeoJson(river_url, name="geojson").add_to(map)
map
Dataset: For the topo JSON overlay example
json.load()
import json
CHOROPLETH and HEATMAPS with FOLIUM:
A choropleth map is a type of statistical thematic map that uses varying intensity of color to aggregate a concrete summary of a geographic characteristic. For Example: population desity, unemployment rate.
To create a Choropleth map, we need a GeoJSon file that represents what we want to plot.
Let's create a
climate_url = ('https://raw.githubusercontent.com/michaelx/climate/master/climate.json')
import pandas as pd
climate_data = pd.read_json(climate_url)
map = folium.Map(location=[0,0], zoom_start=2, tiles = 'cartodbpositron')
map
Conclusion
!pip install opendatasets --upgrade --quiet
import opendatasets as od
dataset_url ="https://www.kaggle.com/datasets/daveianhickey/2000-16-traffic-flow-england-scotland-wales"
od.download(dataset_url)
Please provide your Kaggle credentials to download this dataset. Learn more: http://bit.ly/kaggle-creds
Your Kaggle username: himanigulati
Your Kaggle Key: ········
Downloading 2000-16-traffic-flow-england-scotland-wales.zip to ./2000-16-traffic-flow-england-scotland-wales
100%|██████████| 132M/132M [00:02<00:00, 48.1MB/s]
df_acc = pd.read_csv()
# Execute this to save new versions of the notebook
jovian.commit(project="folium-introduction")
[jovian] Detected Colab notebook...
[jovian] Please enter your API key ( from https://jovian.ai/ ):
API KEY: ··········
[jovian] Error: The current API key is invalid or expired.
[jovian] Please enter your API key ( from https://jovian.ai/ ):
API KEY: