Search code examples
plotlyplotly-dashplotly-express

How to serve an animated plotly-express figure in dash?


I tried to show this example from the plotly-exress homepage in dash.

import plotly.express as px
gapminder = px.data.gapminder()
px.scatter(gapminder, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",
           size="pop", color="continent", hover_name="country",
           log_x=True, size_max=55, range_x=[100,100000], range_y=[25,90])

Like this:

import plotly_express as px
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output

gapminder = px.data.gapminder()

dimensions = []

app = dash.Dash(
    __name__, external_stylesheets=["https://codepen.io/chriddyp/pen/bWLwgP.css"]
)

app.layout = html.Div(
    [
        html.H1("Gapminder data"),
        dcc.Graph(id="graph", style={"width": "75%", "display": "inline-block"}),
    ]
)

@app.callback(Output("graph", "figure"), [])
def make_figure():
    return px.scatter(gapminder, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",
                      size="pop", color="continent", hover_name="country",
                      log_x=True, size_max=55, range_x=[100,100000], range_y=[25,90])


app.run_server(debug=True)

Though, only an empty figure shows up.


Solution

  • Edit: you need the latest version of Dash and Dash Core Components to render animation frames.

    In this case it's because your callback never fires, because the second argument is an empty list (i.e. it doesn't depend on any inputs).

    If you inline the figure into the layout, it will render:

    import plotly_express as px
    import dash
    import dash_html_components as html
    import dash_core_components as dcc
    from dash.dependencies import Input, Output
    
    gapminder = px.data.gapminder()
    
    dimensions = []
    
    app = dash.Dash(
        __name__, external_stylesheets=["https://codepen.io/chriddyp/pen/bWLwgP.css"]
    )
    
    app.layout = html.Div(
        [
            html.H1("Gapminder data"),
            dcc.Graph(id="graph", style={"width": "75%", "display": "inline-block"},
            figure=px.scatter(gapminder, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",
                          size="pop", color="continent", hover_name="country",
                          log_x=True, size_max=55, range_x=[100,100000], range_y=[25,90])),
        ]
    )
    
    
    app.run_server(debug=True)
    

    Or you could wire up you callback to depend on an input that does change, and it will fire and populate the figure :)