An interactive choropleth map in Folium visualizes geospatial data by shading geographic regions according to a numeric variable and allows user interaction such as panning, zooming, and tooltip pop-ups.
An interactive choropleth map shades geographic areas—states, counties, countries—based on the magnitude of a numerical variable, and lets viewers pan, zoom, and reveal contextual tooltips. In Python, the folium
library makes building such maps straightforward by combining Leaflet.js capabilities with a pure-Python API.
Spatial data is everywhere: public health statistics by county, sales by region, election results by district. A static chart forces readers to parse hundreds of data points at once, while an interactive choropleth lets them explore details on demand. Folium removes the front-end friction—you write Python, and Folium emits interactive, browser-ready HTML.
A JSON format for encoding geographic features and their properties. Folium expects your region boundaries in GeoJSON or TopoJSON.
A gradient that maps your numerical variable onto colors (e.g., light ⇢ dark). Folium integrates with branca.colormap
for custom scales.
UI elements that appear when the user hovers or clicks a region, typically showing the region’s name and metric value.
Allows toggling multiple data layers on/off. Handy for side-by-side comparisons (e.g., population vs. income).
pip install folium geopandas branca
You can download ready-made GeoJSON files from sources like GADM or eric.clst.org. Alternatively, convert a shapefile with geopandas
:
import geopandas as gpd
shp = gpd.read_file("cb_2023_us_state_5m.shp")
shp.to_file("us_states.geojson", driver="GeoJSON")
Your DataFrame must contain a key that matches a property in the GeoJSON. Example:
import pandas as pd
state_data = pd.read_csv("state_unemployment.csv") # columns: state, rate
import folium
m = folium.Map(
location=[38.5, -96],
zoom_start=4,
tiles="cartodbpositron" # light background for better contrast
)
folium.Choropleth(
geo_data="us_states.geojson",
data=state_data,
columns=["state", "rate"],
key_on="feature.properties.NAME", # property in GeoJSON
fill_color="YlGnBu",
fill_opacity=0.8,
line_opacity=0.2,
legend_name="Unemployment Rate (%)",
nan_fill_color="white",
).add_to(m)
folium.GeoJson(
"us_states.geojson",
style_function=lambda x: {"fillOpacity": 0}, # keep style from Choropleth
tooltip=folium.features.GeoJsonTooltip(
fields=["NAME"],
aliases=["State:"],
localize=True,
sticky=False,
labels=True,
toLocaleString=True,
),
).add_to(m)
m.save("unemployment_map.html") # or display in Jupyter by just `m`
legend_name
parameter and folium.map.CustomPane
can host credits.Viridis
or Cividis
).If your data lives in a SQL warehouse (Snowflake, Redshift, BigQuery), Galaxy’s modern SQL editor can generate the aggregated table that feeds your Folium map. Write, test, and share the query in Galaxy, then export the results to a CSV or directly fetch them via a DB-API client in Python for visualization.
Your choropleth renders blank because key_on
doesn’t match any GeoJSON properties. Inspect a sample feature (print(json.dumps(geojson['features'][0], indent=2))
) to confirm the property path.
Shapefile in EPSG:3857 but map expects EPSG:4326 (WGS84). Reproject with shp.to_crs(4326)
before export.
Mapping raw population skews perception by area size. Compute per-capita metrics in SQL or Pandas before mapping.
For multi-temporal data, you can animate choropleths using the TimeSliderChoropleth
plugin. For very large GeoJSONs (>5 MB), consider simplifying geometry with shp.simplify(0.01)
or using vector tiles.
Folium empowers Python users to build publication-quality, interactive choropleth maps with only a few dozen lines of code. Clean data joins, thoughtful color scales, and performance-minded geometry choices separate a good map from a great one.
Spatial insights drive decisions in public policy, marketing, supply chain, and epidemiology. An interactive choropleth lets non-technical stakeholders explore variances across regions intuitively and self-serve answers. Building the map in Folium uses familiar Python instead of JavaScript, slashing development time and lowering the skill barrier.
Use perceptually uniform, color-blind-friendly scales such as Viridis
, Cividis
, or YlGnBu
. Folium passes these directly to Leaflet’s color brewer schemes.
Folium exports static HTML, but you can embed the map in a Dash or Streamlit app and update the underlying GeoJSON layer on callbacks for interactivity.
Query the database from Python using SQLAlchemy or a database driver. Galaxy’s SQL editor can craft, optimize, and share the query, then you can fetch it directly into your Pandas DataFrame for mapping.
Use the nan_fill_color
parameter (e.g., set to "lightgray"
) so regions with no data are visually distinct but not misleading.