plotly / plotly.py

The interactive graphing library for Python :sparkles: This project now includes Plotly Express!
https://plotly.com/python/
MIT License
15.93k stars 2.53k forks source link

ScatterMapbox subplots not working #1728

Closed Timost closed 2 weeks ago

Timost commented 5 years ago

Hi, First of all thank you for making plotly. It's amazing. I've been trying to make a subplot of ScatterMapbox (e.g.: Two maps, one below the other) without success. I'm trying this in a jupyter notebook:

The code I use is:

fig = make_subplots(
    rows=2, cols=1,
    specs=[[{'type': 'mapbox'}],[{'type': 'mapbox'}]],
    subplot_titles=('Montreal 1','Montreal 2'),
)

fig.add_trace(go.Scattermapbox(
        lat=['45.5017'],
        lon=['-73.5673'],
        mode='markers',
        marker=go.scattermapbox.Marker(
            size=14
        ),
        text=['Montreal'],
    ), row=1, col=1
)

fig.add_trace(go.Scattermapbox(
        lat=['45.6017'],
        lon=['-73.7673'],
        mode='markers',
        marker=go.scattermapbox.Marker(
            size=14
        ),
        text=['Montreal 2'],
    ), row=2, col=1
             )

fig.update_layout(
    hovermode='closest',
    mapbox=go.layout.Mapbox(
        accesstoken=mapbox_access_token,
        bearing=0,
        center=go.layout.mapbox.Center(
            lat=45,
            lon=-73
        ),
        pitch=0,
        zoom=5
    )
)

fig.show()

This results in an empty map: Screenshot from 2019-08-19 20-04-14 In my browser console I have:

Error: No valid mapbox style found, please set `mapbox.style` to one of:
open-street-map, white-bg, carto-positron, carto-darkmatter, stamen-terrain, stamen-toner, stamen-watercolor
or register a Mapbox access token to use a Mapbox-served style.

Passing a mapbox_style to the layout does not seem to solve the issue.

Note that running the simple montreal example from the doc works properly, even adding a single map to the subplot works too:

fig = make_subplots(
    rows=2, cols=1,
    specs=[[{"type": "mapbox"}],[{"type": "mapbox"}]],
    subplot_titles=("Montreal 1","Montreal 2"),
)

fig.add_trace(go.Scattermapbox(
        lat=['45.5017'],
        lon=['-73.5673'],
        mode='markers',
        marker=go.scattermapbox.Marker(
            size=14
        ),
        text=['Montreal'],
    ), row=1, col=1
)

fig.update_layout(
    hovermode='closest',
    mapbox=go.layout.Mapbox(
        accesstoken=mapbox_access_token,
        bearing=0,
        center=go.layout.mapbox.Center(
            lat=45,
            lon=-73
        ),
        pitch=0,
        zoom=5
    )
)

fig.show()

I've tried passing multiple Scattermapbox to a figure's data but this results in two mapbox layers in the same map. At this point I'm starting to think that subplots are not supported with scattermapbox but as could not find anything regarding this in the docs, I'm probably missing something.

gmleon commented 4 years ago

Hi, I have the same issue using the Mapbox choropleth. Any updates?

Timost commented 4 years ago

Personally I gave up trying to do that.

emmanuelle commented 4 years ago

It seems indeed that mapbox traces don't interact well with subplots. You can still define more manually the domain of subplots as explained in https://community.plot.ly/t/subloting-mapbox-in-jupyter-notebook/16126. Below is an example with a more recent syntax

import plotly.graph_objects as go
fig = go.Figure()

fig.add_trace(
    go.Scattermapbox(
        lat=['45.5017'],
        lon=['-73.5673'],
        mode='markers',
        marker=dict(
            size=14
        ),
        text=['Montreal'],
        subplot='mapbox',
    ))
fig.add_trace(  
    go.Scattermapbox(
        lat=['45.5017'],
        lon=['-73.5673'],
        mode='markers',
        marker=dict(
            size=14
        ),
        text=['Montreal'],
        subplot='mapbox2',
    ))

fig.update_layout(
    autosize=True,
    hovermode='closest',
    mapbox=dict(
        style='open-street-map',
        domain={'x': [0, 0.4], 'y': [0, 1]},
        bearing=0,
        center=dict(
            lat=45,
            lon=-73
        ),
        pitch=0,
        zoom=5
    ),
        mapbox2=dict(
        style='open-street-map',
        domain={'x': [0.6, 1.0], 'y': [0, 1]},
        bearing=0,
        center=dict(
            lat=45,
            lon=-73
        ),
        pitch=0,
        zoom=5
    ),
)

image

gmleon commented 4 years ago

Thank you for your quick replies!

It just worked for me using the update_layout method like this:

fig.update_layout(mapbox_style="carto-positron", mapbox2_style="carto-positron" )

While printing out my figure's layout print(fig.layout), I noticed that the problem is that only the first subplot keeps its original mapbox_style.

But for using more than 1 subplot, you need to set mapbox2_style, mapbox3_style, and so on.

empet commented 4 years ago

What Plotly version are you running? With 4.5.2 the usual code for defining mapbox-type subplots, and updating layout works as expected:

from plotly.subplots import make_subplots
import plotly.graph_objects as go
mapboxt = open(".mapbox_token").read().rstrip() #my mapbox_access_token 
fig = make_subplots(
    rows=1, cols=2, subplot_titles=('Montreal 1', 'Montreal 2'),
    specs=[[{"type": "mapbox"}, {"type": "mapbox"}]]
)

fig.add_trace(go.Scattermapbox(
        lat=[45.5017],
        lon=[-73.5673],
        mode='markers',
        marker_size=14,   
        text=['Montreal 1'],
    ), 1, 1)

fig.add_trace(go.Scattermapbox(
        lat=[45.6017],
        lon=[-73.7673],
        mode='markers',
        marker_size=14,
        text=['Montreal 2'],
    ), 1, 2)
fig.update_layout(
    autosize=True,
    hovermode='closest')

#update the common attributes:
fig.update_mapboxes(
        bearing=0,
        accesstoken=mapboxt,
        center=dict(
            lat=45,
            lon=-73
        ),
        pitch=0,
        zoom=5)

#update different styles:
fig.update_layout(mapbox_style='open-street-map', mapbox2_style='light')

mapbox_subplots

bandersen23 commented 3 years ago

@Timost If you want the styles to be the same across all of your subplots you can also run:

fig.update_mapboxes(style='open-street-map)

This will mean you won't need to call add mapbox{n}_style n times.

Timost commented 3 years ago

@bandersen23 Wow thank you for the answer ! Good to know ! I'll keep that I mind for next time.

mmonto95 commented 2 years ago

@bandersen23 Life saver!

gvwilson commented 2 weeks ago

@archmoj is this addressed by your recent work?

archmoj commented 2 weeks ago

@gvwilson I think we may close this considering some fixes to mapbox since 2020. If there the users encounter it again in latest versions please feel free to reopen it. Thank you!

archmoj commented 2 weeks ago

@archmoj is this addressed by your recent work?

Possibly related to https://github.com/plotly/plotly.js/pull/7068. Let's see if these options would be available via maplibre? cc: @birkskyum

birkskyum commented 2 weeks ago

@archmoj , is there a python playground / REPL / kitchensink, similar to the npm run start javascript one?

What is the best way to try out this in a python environment using the my local fork?

archmoj commented 2 weeks ago

@birkskyum There is a way using this script and a successful run CircleCI run of plotly.js/publish-dist job. But it's not very straightforward. Here I suggest we wait for a plotly.js RC first (i.e. possibly today) and then when we merge plotly.py doc examples to master including maplibre, then it should be easier to test out these details. Thank you!