Animations show change over time memorably, as in the classic Gapminder chart, with a single extra argument.
In Plotly Express, adding animation_frame="year" creates one frame per value of that column, plus a slider and play/pause buttons. animation_group="country" tells Plotly which points are the same object across frames, so they move smoothly instead of reappearing.
px.scatter(df, x="gdpPercap", y="lifeExp", size="pop", color="continent",
animation_frame="year", animation_group="country",
range_x=[100, 100_000], range_y=[25, 90], log_x=True)Always set range_x and range_y: axis ranges are computed for the first frame only, so later data can fly off the chart.
Under the hood the figure gets fig.frames, a list of go.Frame objects each holding its own data (and optionally layout), plus layout.updatemenus (the buttons) and layout.sliders. The initial fig.data is the first frame. You can build this yourself with graph objects for custom animations, and change speed through the button's animation arguments:
fig.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 300Plotly animates by interpolating between frames, which works well for scatter and bar traces; other trace types may just jump between states.
Animations suit exploration and presentations; for printed reports, small multiples (facets) of a few chosen years usually communicate better.
Example
import plotly.express as px
df = px.data.gapminder()
fig = px.scatter(
df, x="gdpPercap", y="lifeExp", size="pop", size_max=45,
color="continent", hover_name="country", log_x=True,
animation_frame="year", animation_group="country",
range_x=[200, 60_000], range_y=[25, 90],
)
print(len(fig.frames)) # 12: one per year
print(fig.frames[0].name, fig.frames[-1].name) # 1952 2007
print(len(fig.layout.sliders[0].steps)) # 12
print(fig.layout.updatemenus[0].buttons[0].method) # animate (the play button)
fig.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 300
fig.write_html("gapminder_anim.html")Remember
animation_framecreates frames, a slider and play buttonsanimation_groupkeeps object identity across frames- Fix
range_x/range_y, since ranges come from the first frame
Watch out for
- Leaving axis ranges automatic, so points leave the visible area in later frames.