In [1]:
import os
import folium

print(folium.__version__)
0.6.0+159.g84a27d0.dirty

GeoJSON and choropleth

A few examples of how to do that with folium.

Using GeoJson

Let us load a GeoJSON file representing the US states.

In [2]:
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 :

In [3]:
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
Out[3]:

Note that you can avoid loading the file on yourself ; in simply providing a file path.

In [4]:
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
Out[4]:

You can pass a geopandas object.

In [5]:
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
Out[5]:

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:

In [6]:
m = 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
Out[6]:

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:

In [7]:
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
Out[7]:

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:

In [8]:
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)
Out[8]:
State Unemployment
0 AL 7.1
1 AK 6.8
2 AZ 8.1
3 AR 7.2
4 CA 10.1

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.

In [9]:
from branca.colormap import linear

colormap = linear.YlGn_09.scale(
    unemployment.Unemployment.min(),
    unemployment.Unemployment.max())

print(colormap(5.0))

colormap
#d8f0a3
Out[9]:
3.210.3

We need also to convert the table into a dictionnary, in order to map a feature to it's unemployment value.

In [10]:
unemployment_dict = unemployment.set_index('State')['Unemployment']

unemployment_dict['AL']
Out[10]:
7.0999999999999996

Now we can do the choropleth.

In [11]:
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
Out[11]:

Of course, if you can create and/or use a dictionnary providing directly the good color. Thus, the finishing seems faster:

In [12]:
color_dict = {key: colormap(unemployment_dict[key]) for key in unemployment_dict.keys()}
In [13]:
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
Out[13]:

Note that adding a color legend may be a good idea.

In [14]:
colormap.caption = 'Unemployment color scale'
colormap.add_to(m)

m.save(os.path.join('results', 'GeoJSON_and_choropleth_7.html'))

m
Out[14]: