Black Lives Matter. Please consider donating to Black Girls Code today.

Dash Mapbox issues. Map shows up as scatter graph

Hi all,

I’m trying to integrate a mapbox map into my existing Dash dashboard. Using an online example I got a working version when I’m just only displaying a map. This is however not using any callbacks:

#import dash and plotly
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go

mapbox_access_token = 'XXXX'

app = dash.Dash(__name__)


datamap = go.Data([go.Scattermapbox(
    lat = ['38.91427', '38.91538', '38.91458',
        '38.92239', '38.93222', '38.90842',
        '38.91931', '38.93260', '38.91368',
        '38.88516', '38.921894', '38.93206',
        '38.91275'
    ],
    lon = ['-77.02827', '-77.02013', '-77.03155',
        '-77.04227', '-77.02854', '-77.02419',
        '-77.02518', '-77.03304', '-77.04509',
        '-76.99656', '-77.042438', '-77.02821',
        '-77.01239'
    ],
    mode = 'markers+lines',
    line = dict(width = 2),
    marker = go.Marker(
        size = 11
      )
    )])

layoutmap = go.Layout(
    height = 700,
    autosize = True,
    showlegend = False,
    hovermode = 'closest',
    geo = dict(
        projection = dict(type = "equirectangular"),
        ),
    mapbox = dict(
        accesstoken = mapbox_access_token,
        bearing = 1,
        center = dict(
            lat = 38.92,
            lon = -77.07
            ),
        pitch = 0,
        zoom = 5,
        style = 'outdoors'
    ),
)

fig = dict( data=datamap, layout=layoutmap )  


app.layout = html.Div([dcc.Graph(id='graph', figure=fig)])

if __name__ == '__main__':
    app.run_server(host='127.0.0.1', port=8053, debug=True)

My existing app uses a graph and some sliders. For demonstration purposes I just used another online sample scatter graph. The issue also occurs with this example. When I’m trying to mix a scatter graph with a map, than the map shows up as a graph. In the example with just the solo map the HTML graph element has an additional ‘figure=fig’ in the dash ‘dcc.Graph(id=‘map’)’ component. However when I use this in the mixed scatter graph with map dash I will get an error (see below). When I remove ‘figure=fig’ the Dash works, but then the map shows up as scatterplot graph. Any ideas?

Import dash and plotly

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd

mapbox_access_token = ‘XXXXX’

app = dash.Dash(name)

df = pd.read_csv(
https://raw.githubusercontent.com/plotly/
‘datasets/master/gapminderDataFiveYear.csv’)

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(name, external_stylesheets=external_stylesheets)

app.layout = html.Div([
dcc.Graph(id=‘graph-with-slider’),
dcc.Slider(
id=‘year-slider’,
min=df[‘year’].min(),
max=df[‘year’].max(),
value=df[‘year’].min(),
marks={str(year): str(year) for year in df[‘year’].unique()}
),
dcc.Graph(id=‘map’, figure=fig)
])

@app.callback(
dash.dependencies.Output(‘graph-with-slider’, ‘figure’),
[dash.dependencies.Input(‘year-slider’, ‘value’)])
def update_figure(selected_year):
filtered_df = df[df.year == selected_year]
traces = []
for i in filtered_df.continent.unique():
df_by_continent = filtered_df[filtered_df[‘continent’] == i]
traces.append(go.Scatter(
x=df_by_continent[‘gdpPercap’],
y=df_by_continent[‘lifeExp’],
text=df_by_continent[‘country’],
mode=‘markers’,
opacity=0.7,
marker={
‘size’: 15,
‘line’: {‘width’: 0.5, ‘color’: ‘white’}
},
name=i
))

return {
    'data': traces,
    'layout': go.Layout(
        xaxis={'type': 'log', 'title': 'GDP Per Capita'},
        yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
        margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
        legend={'x': 0, 'y': 1},
        hovermode='closest'
    )
}

@app.callback(
dash.dependencies.Output(‘map’, ‘figure’),
[dash.dependencies.Input(‘year-slider’, ‘value’)])
def update_map(selectlocations):

datamap = go.Data([go.Scattermapbox(
    lat = ['38.91427', '38.91538', '38.91458',
        '38.92239', '38.93222', '38.90842',
        '38.91931', '38.93260', '38.91368',
        '38.88516', '38.921894', '38.93206',
        '38.91275'
    ],
    lon = ['-77.02827', '-77.02013', '-77.03155',
        '-77.04227', '-77.02854', '-77.02419',
        '-77.02518', '-77.03304', '-77.04509',
        '-76.99656', '-77.042438', '-77.02821',
        '-77.01239'
    ],
    mode = 'markers+lines',
    line = dict(width = 2),
    marker = go.Marker(
        size = 11,
        text = 'Test',
        hoverinfo = 'text'
      )
    )])

layoutmap = go.Layout(
    height = 700,
    autosize = True,
    showlegend = False,
    hovermode = 'closest',
    geo = dict(
        projection = dict(type = "equirectangular"),
        ),
    mapbox = dict(
        accesstoken = mapbox_access_token,
        bearing = 1,
        center = dict(
            lat = 38.92,
            lon = -77.07
            ),
        pitch = 0,
        zoom = 5,
        style = 'outdoors'
    ),
)

fig = dict( data=datamap, layout=layoutmap )  

return fig

if name == ‘main’:
app.run_server(host=‘127.0.0.1’, port=8051, debug=True)

Error code when using ‘figure=fig’

INFO:werkzeug: * Restarting with stat
An exception has occurred, use %tb to see the full traceback.

SystemExit: 1

/Users/jon/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py:2870: UserWarning:

To exit: use ‘exit’, ‘quit’, or Ctrl-D.

/Users/jon/anaconda3/lib/python3.6/site-packages/spyder/widgets/variableexplorer/utils.py:414: FutureWarning:

‘summary’ is deprecated and will be removed in a future version.

%tb
Traceback (most recent call last):

File “”, line 1, in
runfile(’/Users/jon/Documents/GitHub/Besttime/dash-map-probeerselv2.py’, wdir=’/Users/jon/Documents/GitHub/Besttime’)

File “/Users/jon/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py”, line 705, in runfile
execfile(filename, namespace)

File “/Users/jon/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py”, line 102, in execfile
exec(compile(f.read(), filename, ‘exec’), namespace)

File “/Users/jon/Documents/GitHub/Besttime/dash-map-probeerselv2.py”, line 122, in

File “/Users/jon/anaconda3/lib/python3.6/site-packages/dash/dash.py”, line 1061, in run_server
**flask_run_options)

File “/Users/jon/anaconda3/lib/python3.6/site-packages/flask/app.py”, line 841, in run
run_simple(host, port, self, **options)

File “/Users/jon/anaconda3/lib/python3.6/site-packages/werkzeug/serving.py”, line 737, in run_simple
reloader_type)

File “/Users/jon/anaconda3/lib/python3.6/site-packages/werkzeug/_reloader.py”, line 265, in run_with_reloader
sys.exit(reloader.restart_with_reloader())

SystemExit: 1

In the example code with just the map HTML app.layout is written in the botton of the script. However when doing the callbacks it seems that I had to first describe the layout before I could do the callbacks. Otherwise the callbacks called before the input and output elements have been stated.

Hopefully somebody could guide me a bit.

Thanks you so much.

This is not a issue with mapbox. Just delete the figure=fig in your second code if you are just using callback to update the graph.

A simple example below: (You can see you only need to specify the id for dcc.Graph in the layout)

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go

app = dash.Dash(__name__)

app.layout = html.Div(
    children=[
        dcc.Input(id='input', type='text'),
        dcc.Graph(id='plot'),
        ])

@app.callback(
    Output('plot', 'figure'),
    [Input('input', 'value')]
)
def update_graph_1(input):
    return {'data':[go.Bar(
            x=['giraffes', 'orangutans', 'monkeys'],
            y=[20, 14, 23])]}

if __name__ == '__main__':
    app.run_server(debug=True)

Thanks for the example. I got it to work now.