In [1]:
import os
import folium

print(folium.__version__)


0.3.0.dev

Quickstart

Getting Started

To create a base map, simply pass your starting coordinates to Folium:


In [2]:
m = folium.Map(location=[45.5236, -122.6750])

To display it in a Jupyter notebook, simply ask for the object representation:


In [3]:
m


Out[3]:

To save it in a file:


In [4]:
m.save(os.path.join('results', 'Quickstart_0.html'))

Folium defaults to OpenStreetMap tiles, but Stamen Terrain, Stamen Toner, Mapbox Bright, and Mapbox Control room tiles are built in:


In [5]:
folium.Map(
    location=[45.5236, -122.6750],
    tiles='Stamen Toner',
    zoom_start=13
)


Out[5]:

Folium also supports Cloudmade and Mapbox custom tilesets- simply pass your key to the API_key keyword:

folium.Map(location=[45.5236, -122.6750],
           tiles='Mapbox',
           API_key='your.API.key')

Lastly, Folium supports passing any Leaflet.js compatible custom tileset:

folium.Map(location=[45.372, -121.6972],
           zoom_start=12,
           tiles='http://{s}.tiles.yourtiles.com/{z}/{x}/{y}.png',
           attr='My Data Attribution')

Markers

Folium supports the plotting of numerous marker types, starting with a simple Leaflet style location marker with popup text:


In [6]:
m = folium.Map(
    location=[45.372, -121.6972],
    zoom_start=12,
    tiles='Stamen Terrain'
)

folium.Marker([45.3288, -121.6625], popup='Mt. Hood Meadows').add_to(m)
folium.Marker([45.3311, -121.7113], popup='Timberline Lodge').add_to(m)

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

m


Out[6]:

Folium supports colors and marker icon types (from bootstrap)


In [7]:
m = folium.Map(
    location=[45.372, -121.6972],
    zoom_start=12,
    tiles='Stamen Terrain'
)

folium.Marker(
    location=[45.3288, -121.6625],
    popup='Mt. Hood Meadows',
    icon=folium.Icon(icon='cloud')
).add_to(m)

folium.Marker(
    location=[45.3311, -121.7113],
    popup='Timberline Lodge',
    icon=folium.Icon(color='green')
).add_to(m)

folium.Marker(
    location=[45.3300, -121.6823],
    popup='Some Other Location',
    icon=folium.Icon(color='red', icon='info-sign')
).add_to(m)

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

m


Out[7]:

Folium also supports circle-style markers, with custom size and color:


In [8]:
m = folium.Map(
    location=[45.5236, -122.6750],
    tiles='Stamen Toner',
    zoom_start=13
)

folium.Marker(
    location=[45.5244, -122.6699],
    popup='The Waterfront'
).add_to(m)

folium.CircleMarker(
    location=[45.5215, -122.6261],
    radius=50,
    popup='Laurelhurst Park',
    color='#3186cc',
    fill_color='#3186cc'
).add_to(m)

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

m


Out[8]:

Folium has a convenience function to enable lat/lng popovers:


In [9]:
m = folium.Map(
    location=[46.1991, -122.1889],
    tiles='Stamen Terrain',
    zoom_start=13
)

m.add_child(folium.LatLngPopup())

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

m


Out[9]:

Click-for-marker functionality will allow for on-the-fly placement of markers:


In [10]:
m = folium.Map(
    location=[46.8527, -121.7649],
    tiles='Stamen Terrain',
    zoom_start=13
)

folium.Marker(
    [46.8354, -121.7325],
    popup='Camp Muir'
).add_to(m)

m.add_child(folium.ClickForMarker(popup='Waypoint'))

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

m


Out[10]:

Folium also supports the Polygon marker set from the Leaflet-DVF:


In [11]:
m = folium.Map(
    location=[45.5236, -122.6750],
    zoom_start=13
)

folium.RegularPolygonMarker(
    location=[45.5012, -122.6655],
    popup='Ross Island Bridge',
    fill_color='#132b5e',
    number_of_sides=3,
    radius=10
).add_to(m)

folium.RegularPolygonMarker(
    location=[45.5132, -122.6708],
    popup='Hawthorne Bridge',
    fill_color='#45647d',
    number_of_sides=4,
    radius=10
).add_to(m)

folium.RegularPolygonMarker(
    location=[45.5275, -122.6692],
    popup='Steel Bridge',
    fill_color='#769d96',
    number_of_sides=6,
    radius=10
).add_to(m)

folium.RegularPolygonMarker(
    location=[45.5318, -122.6745],
    popup='Broadway Bridge',
    fill_color='#769d96',
    number_of_sides=8,
    radius=10
).add_to(m)

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

m


Out[11]:

Vincent/Vega Markers

Folium enables passing vincent visualizations to any marker type, with the visualization as the popover:


In [12]:
vis1 = os.path.join('data', 'vis1.json')
vis2 = os.path.join('data', 'vis2.json')
vis3 = os.path.join('data', 'vis3.json')

In [13]:
import json

m = folium.Map(
    location=[46.3014, -123.7390],
    zoom_start=7,
    tiles='Stamen Terrain'
)

folium.RegularPolygonMarker(
    location=[47.3489, -124.708],
    fill_color='#43d9de',
    radius=12,
    popup=folium.Popup(max_width=450).add_child(
        folium.Vega(json.load(open(vis1)), width=450, height=250))
).add_to(m)

folium.RegularPolygonMarker(
    location=[44.639, -124.5339],
    fill_color='#43d9de',
    radius=12,
    popup=folium.Popup(max_width=450).add_child(
        folium.Vega(json.load(open(vis2)), width=450, height=250))
).add_to(m)

folium.RegularPolygonMarker(
    location=[46.216, -124.1280],
    fill_color='#43d9de',
    radius=12,
    popup=folium.Popup(max_width=450).add_child(
        folium.Vega(json.load(open(vis3)), width=450, height=250))
).add_to(m)

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

m


Out[13]:

For more information about popups, please visit Popups.ipynb

GeoJSON/TopoJSON Overlays

Both GeoJSON and TopoJSON layers can be passed to the map as an overlay, and multiple layers can be visualized on the same map:


In [14]:
antarctic_ice_edge = os.path.join('data', 'antarctic_ice_edge.json')
antarctic_ice_shelf_topo = os.path.join('data', 'antarctic_ice_shelf_topo.json')

m = folium.Map(
    location=[-59.1759, -11.6016],
    tiles='Mapbox Bright',
    zoom_start=2
)

folium.GeoJson(
    open(antarctic_ice_edge),
    name='geojson'
).add_to(m)

folium.TopoJson(
    open(antarctic_ice_shelf_topo),
    'objects.antarctic_ice_shelf',
    name='topojson'
).add_to(m)

folium.LayerControl().add_to(m)

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

m


Out[14]:

Choropleth maps

Folium allows for the binding of data between Pandas DataFrames/Series and Geo/TopoJSON geometries. Color Brewer sequential color schemes are built-in to the library, and can be passed to quickly visualize different combinations:


In [15]:
import pandas as pd

state_geo = os.path.join('data', 'us-states.json')
state_unemployment = os.path.join('data', 'US_Unemployment_Oct2012.csv')

state_data = pd.read_csv(state_unemployment)

# Let Folium determine the scale.
m = folium.Map(location=[48, -102], zoom_start=3)

m.choropleth(
    geo_path=state_geo,
    data=state_data,
    columns=['State', 'Unemployment'],
    key_on='feature.id',
    fill_color='YlGn',
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name='Unemployment Rate (%)'
)

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

m


Out[15]:

Folium creates the legend on the upper right based on a D3 threshold scale, and makes the best-guess at values via quantiles. Passing your own threshold values is simple:


In [16]:
# Control the scale.
from branca.utilities import split_six

threshold_scale = split_six(state_data['Unemployment'])

m = folium.Map(location=[48, -102], zoom_start=3)

m.choropleth(
    geo_path=state_geo,
    data=state_data,
    columns=['State', 'Unemployment'],
    key_on='feature.id',
    fill_color='BuPu',
    fill_opacity=0.7,
    line_opacity=0.5,
    legend_name='Unemployment Rate (%)',
    threshold_scale=threshold_scale,
    reset=True
)

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

m


Out[16]:

By binding data via the Pandas DataFrame, different datasets can be quickly visualized. In the following example, the df DataFrame contains six columns with different economic data, a few of which we will visualize:


In [17]:
unemployment = pd.read_csv(state_unemployment)

m = folium.Map([43, -100], zoom_start=4)

m.choropleth(
    geo_str=open(state_geo).read(),
    data=unemployment,
    columns=['State', 'Unemployment'],
    key_on='feature.id',
    fill_color='YlGn',
    threshold_scale=[3.0, 7.0, 8.0, 9.0, 9.0]
)

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

m


Out[17]:

Styling function


In [18]:
import branca

county_data = os.path.join('data', 'us_county_data.csv')
county_geo = os.path.join('data', 'us_counties_20m_topo.json')

df = pd.read_csv(county_data, na_values=[' '])


colorscale = branca.colormap.linear.YlOrRd.scale(0, 50e3)
employed_series = df.set_index('FIPS_Code')['Employed_2011']


def style_function(feature):
    employed = employed_series.get(int(feature['id'][-5:]), None)
    return {
        'fillOpacity': 0.5,
        'weight': 0,
        'fillColor': '#black' if employed is None else colorscale(employed)
    }

m = folium.Map(
    location=[48, -102],
    tiles='cartodbpositron',
    zoom_start=3
)

folium.TopoJson(
    open(county_geo),
    'objects.us_counties_20m',
    style_function=style_function
).add_to(m)

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

m


Out[18]:

In [19]:
colorscale = branca.colormap.linear.YlGnBu.scale(0, 30)

employed_series = df.set_index('FIPS_Code')['Unemployment_rate_2011']


def style_function(feature):
    employed = employed_series.get(int(feature['id'][-5:]), None)
    return {
        'fillOpacity': 0.5,
        'weight': 0,
        'fillColor': '#black' if employed is None else colorscale(employed)
    }

m = folium.Map(
    location=[48, -102],
    tiles='cartodbpositron',
    zoom_start=3
)

folium.TopoJson(
    open(county_geo),
    'objects.us_counties_20m',
    style_function=style_function
).add_to(m)

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

m


Out[19]:

In [20]:
colorscale = branca.colormap.linear.PuRd.scale(0, 100000)

employed_series = df.set_index('FIPS_Code')['Median_Household_Income_2011'].dropna()


def style_function(feature):
    employed = employed_series.get(int(feature['id'][-5:]), None)
    return {
        'fillOpacity': 0.5,
        'weight': 0,
        'fillColor': '#black' if employed is None else colorscale(employed)
    }

m = folium.Map(
    location=[48, -102],
    tiles='cartodbpositron',
    zoom_start=3)


folium.TopoJson(
    open(county_geo),
    'objects.us_counties_20m',
    style_function=style_function
).add_to(m)

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

m


Out[20]: