How to update a choropleth map

I’m trying to a webpage, this page includes a choropleth map of the world with data based on the selected year. I want to be able to change the year and with that also update the map to match that year. I prefer to do this with the Dash slider, although any other way I would appreciate as well.

I’ve tried updating other graphs such as line charts with the text input, and that worked, but when i changed it to a choropleth map it stopped updating. It now only creates the map but updates on it don’t show up. I’ve put some print text in the update function and it confirmed that it is actually called when I change the input, but the graph just doesn’t update.

The layout:with the dcc.input i want to update the html.Div ‘my-div’

app.layout = html.Div( children=[
    html.H1(
        children='UN Sustainable Development goal: Poverty',
        style={
            'textAlign': 'center',
            'color': colors
        }
    ),
    dcc.Input(id='my-id',value='30', type='text'),
    html.Div(id='my-div')
    ,
    daq.Slider(
        id='my-daq-slider',
        min=1,
        max=sliderlength,
        step=1,
    ),
    html.Div(id='slider-output')




],        style={
        'textAlign': 'center'
    })

The update part

@app.callback(
    Output('my-div', 'children'),
    [Input('my-id', 'value')])

def update_output_div(input_value):
    return dcc.Graph(
        id='my-div',

        figure={'data': [go.Choropleth(
    locations = df_pov['Country Code'],
    z = df_pov.iloc[:,int(input_value)],
    text = df_pov['Country Name'],

    autocolorscale = True,
    reversescale = False,
    marker = go.choropleth.Marker(
        line = go.choropleth.marker.Line(
            color = 'rgb(180,180,180)',
            width = 0.5
        )),
    colorbar = go.choropleth.ColorBar(
        tickprefix = '%',
        title = '%  below 1.90$ '),
)],
                'layout': go.Layout(
    title = go.layout.Title(
        text = list(df_pov)[int(input_value)]
    ),
    geo = go.layout.Geo(
        showframe = False,
        showcoastlines = False,
        projection = go.layout.geo.Projection(
            type = 'equirectangular'
        )
    ),
    annotations = [go.layout.Annotation(
        x = 0.55,
        y = 0.1,
        xref = 'paper',
        yref = 'paper',
        text = 'Source: Kaggle',
        showarrow = False
    )]
)            
        }
    )

What i expected: for the choropleth to update when changing the text input, or slider input. Actual: the map gets created once ( with the same function that should update it), but doesn’t update.

I’m having a similar issue. Below I provide minimal working example (based on an example here: https://plot.ly/python/choropleth-maps/). In my example, the user selects a variable to plot from a dropdown. It seems that the color bar adjusts when the variable being plotted has values outside of the current range. But if I select a variable with a smaller range, the color bars do not adjust. This results, of course, in a map that looks like it has a single color.

Someone responded to this issue on Stackoverflow, but their suggestion did not work for me. https://stackoverflow.com/questions/56086466/how-to-update-choropleth-map-in-dash/56094437

Does anyone have any idea how to force the color bar to adjust appropriately to each callback?

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from dash.dependencies import Input, Output
import plotly.express as px


app = dash.Dash(__name__)
server = app.server

DF = px.data.gapminder().query("year==2007")
OPTIONS = ['lifeExp', 'pop', 'gdpPercap']

app.layout = html.Div([
    dcc.Dropdown(id='var_choice'  , value='lifeExp'  , options=[{'label': i, 'value': i} for i in  OPTIONS]),
    dcc.Graph(id='my-graph'),
])

@app.callback(     Output('my-graph'        , 'figure'    ) ,
                  [Input('var_choice'       , 'value'     ) ] )
def update_figure(var_choice):

    df = DF

    fig = px.choropleth(df,
            locations='iso_alpha'       ,
            color=var_choice            ,
            hover_name='country'        ,
            color_continuous_scale=px.colors.sequential.Plasma)
    return fig
if __name__ == '__main__':
    app.run_server(port=8055, debug=True  )

So, the first graph - life expectancy - is scaled nicely. If I change the variable to population, the scale adjusts. So far so good. However, when I change the variable back to life expectancy, the color bar does not update.



I found one solution to this issue: use “plotly.graph_objects” instead of “plotly.express”. In the example below I let the user decide which package is used to define the figure. When “plotly.graph_objects” is used, the color bar updates as expected. Maybe others can find this useful.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go

app = dash.Dash(__name__)
server = app.server

DF = px.data.gapminder().query("year==2007")
DF.columns
OPTIONS = ['lifeExp', 'pop', 'gdpPercap']
packages = ['go', 'px']

app.layout = html.Div([
    dcc.Dropdown(id='var_choice'  , value='lifeExp'  , options=[{'label': i, 'value': i} for i in  OPTIONS]),
    dcc.Dropdown(id='pkg_choice'  , value='go'       , options=[{'label': i, 'value': i} for i in  packages]),
    dcc.Graph(id='my-graph'),
])

@app.callback(     Output('my-graph'        , 'figure'    ) ,
                  [Input('var_choice'       , 'value'     ) ,
                   Input('pkg_choice'       , 'value'     )  ] )
def update_figure(var_choice, pkg):

    df = DF

    #drop missing values
    df = df.dropna(subset=[var_choice])

    if pkg=='go':
        fig = go.Figure(data=go.Choropleth(
            locations=df['iso_alpha'],
            z=df[var_choice],
            colorscale='Reds',
            text=df['country'], # hover text
        ))
    else:
        fig = px.choropleth(df,
                locations='iso_alpha'       ,
                color=var_choice            ,
                hover_name='country'        ,
                color_continuous_scale=px.colors.sequential.Plasma)

    return fig

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