2

I need to create a scatterplot in plotly, and overlay a line plot on top of it. I found that I can do it if I create the figure using graph objects, and then add the data using plotly express:

scatter = px.scatter(...)
line = px.line(...)
fig = go.Figure(data=scatter.data + line.data)

But the problem is that I need to animate the line plot with a slider, and when I use the graph_objects interface I can't do it.

Do you know if there is a way to do this?

Paca
  • 69
  • 7
  • 1
    Try this https://stackoverflow.com/questions/71060711/how-to-animate-line-in-scatter-plot-using-plotly-express – Hamzah Sep 27 '22 at 07:38
  • The data from the scatter plot and line plot and line plot are independent. I need to animate the line plot while keeping the scatter plot fixed. – Paca Sep 27 '22 at 07:55

2 Answers2

3
  • have simulated two independent data sets (dimensionality of axes and animation is consistent)
  • it's not clear if you want to integrate two animated figures or an animated and fixed figure. Have used former, later would be same just traces from fixed figure would be copied into each target frame
  • it's all about being consistent
    1. integrate the traces
    2. integrate the frames
    3. pick a layout
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

r = np.random.RandomState(22)

# simulate two independent dataframes.  NB some consistency for axes and animation
df_line = pd.DataFrame(
    {
        "animation": np.repeat(list("ABCDE"), 10),
        "x": np.tile(np.linspace(0, 10, 10), 5),
        "y": r.uniform(0, 10, 50),
    }
)

df_scatter = pd.DataFrame(
    {
        "animation": np.repeat(list("ABCDE"), 50),
        "x": np.tile(np.linspace(0, 10, 50), 5),
        "y": r.uniform(0, 10, 250),
    }
)

line = px.line(df_line, x="x", y="y", animation_frame="animation")
scatter = px.scatter(df_scatter, x="x", y="y", animation_frame="animation")

# now integrate, traces, frames and layout
fig = go.Figure(
    data=line.data + scatter.data,
    frames=[
        go.Frame(data=fr1.data + fr2.data, name=fr1.name)
        for fr1, fr2 in zip(line.frames, scatter.frames)
    ],
    layout=scatter.layout,
)

fig

enter image description here

Rob Raymond
  • 29,118
  • 3
  • 14
  • 30
  • Great contribution! I've spent quite some time today trying to get a similar approach working, so I'm really glad you came up with this – vestland Sep 28 '22 at 20:55
  • thanks @vestland BTW recently coded this answer that makes an animated gif easy https://stackoverflow.com/questions/55460434/how-to-export-save-an-animated-bubble-chart-made-with-plotly/73788157#73788157 – Rob Raymond Sep 28 '22 at 21:31
1

I see you've used px.line in your example, so I'd just like to add that you can easily build a figure with Plotly Express with animations and include a fixed trace by simply using:

fig.add_trace()

Below an example that uses the gapminder dataset. For your use-case, if you've set it up with px.line, you should easily be able to make the switch between which traces are animated; the scatter or the line.

Figure

enter image description here

Complete code:

import plotly.express as px
import plotly.graph_objects as go

df = px.data.gapminder()
fig = px.scatter(df, 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],
           # mode = 'markers+lines'
           height = 600, width = 1000
          )

fig.add_trace(go.Scatter(x=[0, 10000, 20000, 30000], y = [40,50,60, 70], mode = 'lines'))

fig.show()
vestland
  • 55,229
  • 37
  • 187
  • 305