import os
import folium
print(folium.__version__)
import json
us_states = os.path.join('data', 'us-states.json')
geo_json_data = json.load(open(us_states))
It is a classical GeoJSON FeatureCollection
(see https://en.wikipedia.org/wiki/GeoJSON) of the form :
{
"type": "FeatureCollection",
"features": [
{
"properties": {"name": "Alabama"},
"id": "AL",
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[-87.359296, 35.00118], ...]]
}
},
{
"properties": {"name": "Alaska"},
"id": "AK",
"type": "Feature",
"geometry": {
"type": "MultiPolygon",
"coordinates": [[[[-131.602021, 55.117982], ... ]]]
}
},
...
]
}
A first way of drawing it on a map, is simply to use folium.GeoJson
:
m = folium.Map([43, -100], zoom_start=4)
folium.GeoJson(geo_json_data).add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_0.html'))
m
Note that you can avoid loading the file on yourself ; in simply providing a file path.
m = folium.Map([43, -100], zoom_start=4)
folium.GeoJson(us_states).add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_1.html'))
m
You can pass a geopandas object.
import geopandas
gdf = geopandas.read_file(us_states)
m = folium.Map([43, -100], zoom_start=4)
folium.GeoJson(
gdf,
).add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_3.html'))
m
Now this is cool and simple, but we may be willing to choose the style of the data.
You can provide a function of the form lambda feature: {}
that sets the style of each feature.
For possible options, see:
Point
and MultiPoint
, see http://leafletjs.com/reference.html#markerm = folium.Map([43, -100], zoom_start=4)
folium.GeoJson(
geo_json_data,
style_function=lambda feature: {
'fillColor': '#ffff00',
'color': 'black',
'weight': 2,
'dashArray': '5, 5'
}
).add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_3.html'))
m
What's cool in providing a function, is that you can specify a style depending on the feature. For example, if you want to visualize in green all states whose name contains the letter 'E', just do:
m = folium.Map([43, -100], zoom_start=4)
folium.GeoJson(
geo_json_data,
style_function=lambda feature: {
'fillColor': 'green' if 'e' in feature['properties']['name'].lower() else '#ffff00',
'color': 'black',
'weight': 2,
'dashArray': '5, 5'
}
).add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_4.html'))
m
Wow, this looks almost like a choropleth. To do one, we just need to compute a color for each state.
Let's imagine we want to draw a choropleth of unemployment in the US.
First, we may load the data:
import pandas as pd
US_Unemployment_Oct2012 = os.path.join('data', 'US_Unemployment_Oct2012.csv')
unemployment = pd.read_csv(US_Unemployment_Oct2012)
unemployment.head(5)
Now we need to create a function that maps one value to a RGB color (of the form #RRGGBB
).
For this, we'll use colormap tools from folium.colormap
.
from branca.colormap import linear
colormap = linear.YlGn_09.scale(
unemployment.Unemployment.min(),
unemployment.Unemployment.max())
print(colormap(5.0))
colormap
We need also to convert the table into a dictionnary, in order to map a feature to it's unemployment value.
unemployment_dict = unemployment.set_index('State')['Unemployment']
unemployment_dict['AL']
Now we can do the choropleth.
m = folium.Map([43, -100], zoom_start=4)
folium.GeoJson(
geo_json_data,
name='unemployment',
style_function=lambda feature: {
'fillColor': colormap(unemployment_dict[feature['id']]),
'color': 'black',
'weight': 1,
'dashArray': '5, 5',
'fillOpacity': 0.9,
}
).add_to(m)
folium.LayerControl().add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_5.html'))
m
Of course, if you can create and/or use a dictionnary providing directly the good color. Thus, the finishing seems faster:
color_dict = {key: colormap(unemployment_dict[key]) for key in unemployment_dict.keys()}
m = folium.Map([43, -100], zoom_start=4)
folium.GeoJson(
geo_json_data,
style_function=lambda feature: {
'fillColor': color_dict[feature['id']],
'color': 'black',
'weight': 1,
'dashArray': '5, 5',
'fillOpacity': 0.9,
}
).add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_6.html'))
m
Note that adding a color legend may be a good idea.
colormap.caption = 'Unemployment color scale'
colormap.add_to(m)
m.save(os.path.join('results', 'GeoJSON_and_choropleth_7.html'))
m