Adding Mapbox Layer to Plotly Map Positioned Over Data Layer

I’m trying to understand how to situate a data layer within a stack of vector layers using Plotly’s Mapbox functionality. I think this is possible with the following approach. Using Mapbox Studio, I’ve created two map styles: one which represents the base map that all data layers should be placed on top of and another which represents the remaining map layers that should be layered on above the data layers.

This example from the Plotly documentation seems to point to the viability of this approach.

Here’s demo code that I put together to try and realize the result I’m after. The last update_layout statement is not adding the Mapbox layer. Not sure what I’m missing here. Any suggestions? Maybe the Mapbox style spec can’t be passed for additional layers?

import plotly.graph_objects as go
import pandas as pd

us_cities = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/us-cities-top-1k.csv")

fig = go.Figure(go.Scattermapbox(lat=us_cities["lat"], lon=us_cities["lon"]))
fig.update_layout(mapbox_style="mapbox://styles/diehl/cl9gh775w000014n2jwfncok7", mapbox_accesstoken=MAPBOX_ACCESS_TOKEN)
fig.update_layout(mapbox_center_lat=38, mapbox_center_lon=-97, mapbox_zoom=3.25)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

fig.update_layout(
    mapbox_layers=[
    {
        "sourcetype": "vector",
        "source": ["mapbox://styles/diehl/cl9gha8ta000914qm137qf52q"]
    }
])

fig.show()

Took a small step forward in that I got something to render. Replacing the last fig.update_layout statement with the following causes additional circles to be rendered instead of the vector tiles which is strange. The vector tiles referred to here correspond to the border for the state of New Mexico. Not complex by any means. Why that vector tile layer is showing up as additional circles I assume is due to the plot being a scatter plot. Any thoughts about how to get around this would be greatly appreciated!

fig.update_layout(
mapbox_layers=[
{
“sourcetype”: “vector”,
“source”: [‘https://api.mapbox.com/v4/diehl.3rvgqhks/{z}/{x}/{y}.mvt’],
“sourcelayer”: “new_mexico_bnd”
}
])

For what it is worth, I noticed in the Chrome dev console the following message: “Geometry exceeds allowed extent, reduce your vector tile buffer size

After much digging in the documentation, it became clear that my strategy is misguided. The more appropriate approach is to specify the full vector stack for the basemap and then use the below functionality to tell Plotly where to slot a particular trace into the basemap. Here’s a working example.

import plotly.graph_objects as go
import pandas as pd

us_cities = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/us-cities-top-1k.csv")
token = <MAPBOX_ACCESS_TOKEN>

fig = go.Figure(go.Scattermapbox(lat=us_cities["lat"], lon=us_cities["lon"]))
fig.update_layout(mapbox_style="mapbox://styles/mapbox/light-v10", mapbox_accesstoken=token)
fig.update_layout(mapbox_center_lat=38, mapbox_center_lon=-97, mapbox_zoom=3.25)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

# Statement that tells Plotly where to insert the trace into the basemap
fig.update_traces(below="aeroway-polygon", selector=dict(type='scattermapbox'))

fig.show()
2 Likes