Location is a natural dimension for business and public data, and Plotly makes interactive maps a one-liner.
Plotly has two families of maps.
Outline (geo) maps draw country and region shapes without a tile server: px.choropleth colors regions, and px.scatter_geo / px.line_geo place points and lines.
px.choropleth(df, locations="iso_alpha", color="lifeExp",
hover_name="country", projection="natural earth")locations are matched by locationmode: ISO-3 codes by default, or "USA-states" for two-letter state codes. Country names are supported but matched strictly in Plotly 7, so prefer ISO-3 codes. For other regions, pass a GeoJSON geojson= and featureidkey="properties.id" to say which property matches your locations column. Since Plotly 7, geo maps zoom to fit the plotted locations by default (fitbounds="locations").
Tile maps draw on a street-map background rendered by MapLibre: px.scatter_map(df, lat="lat", lon="lon", zoom=10), px.density_map for heatmaps of many points, px.choropleth_map for GeoJSON regions on tiles. Choose the background with map_style ("open-street-map", "carto-positron", "carto-darkmatter" ...); these need no access token. The older Mapbox-based functions (scatter_mapbox and friends) were removed in Plotly 7.
Use a sequential color scale for quantities and normalize by population or area: raw counts on a choropleth mostly show where people live.
Example
import plotly.express as px
df = px.data.gapminder().query("year == 2007")
fig = px.choropleth(df, locations="iso_alpha", color="lifeExp",
hover_name="country", color_continuous_scale="Viridis",
projection="natural earth")
print(fig.data[0].type, fig.data[0].locationmode) # choropleth None (plotly.js default: ISO-3)
cities = px.data.carshare() # Montreal car-share points
tiles = px.scatter_map(cities, lat="centroid_lat", lon="centroid_lon",
color="peak_hour", size="car_hours", size_max=12,
zoom=10, map_style="carto-positron")
print(tiles.data[0].type) # scattermap
print(tiles.layout.map.style) # carto-positron
fig.write_html("life_map.html")
tiles.write_html("carshare.html")Remember
- Geo maps (choropleth, scatter_geo) need no tiles; tile maps use MapLibre
- Match regions by ISO-3 codes, state codes, or GeoJSON with
featureidkey - In Plotly 7 use
scatter_map/choropleth_map; the mapbox functions are gone
Watch out for
- Mapping raw counts on a choropleth, which mostly reflects population rather than the rate you care about.