Search code examples
pythonanimationplotly-python

Problem with animation of multiple traces with plotly


I'm trying to animate multiple tracks with Python plotly.
The code is:

import pandas as pd
import plotly.express as px
df = pd.read_csv("orbite.csv")
fig=px.scatter(df,x="X1",y="Y1",animation_frame="time",range_x=[-6,1],range_y=[-5,2])\

fig.add_scatter(df,x="X2",y="Y2",animation_frame="time",range_x=[-6,1],range_y=[-5,2])

fig.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 20
fig.update_layout(transition = {"duration": 20})
fig.show()

This is the data file:

      time         X1         Y1        X2         Y2
0        1  -0.001000   0.000000  0.000000  10.000000

1        2  -0.001000   0.000000 -0.035000   9.940000

2        3  -0.000951   0.000049 -0.070000   9.890000

3        4  -0.000853   0.000148 -0.105000   9.830000

4        5  -0.000707   0.000297 -0.140000   9.780000

The program works fine with only one animation, but if I add fig.add_scatter(), I get the error:

The 'alignmentgroup' property is a string and must be specified as:
  - A string
  - A number that will be converted to a string

What's wrong?


Solution

  • add_scatter is not using the same functionality as px.scatter (see e.g. https://stackoverflow.com/a/67529369/9501624), and hence cannot be used to "combine animations".

    The only way I know of is to "rebuild" the frames in a new figure based on graph_objects and frames (see e.g. Animating & overlaying multiple plots with plotly):

    enter image description here

    import pandas as pd
    import plotly.express as px
    from plotly import graph_objects as go
    
    data = {
        "time": [1, 2, 3, 4, 5],
        "X1": [0.5, 0.4, 0.3, 0.2, 0.1],
        "Y1": [0.5, 0.4, 0.3, 0.2, 0.1],
        "X2": [-0.5, -0.4, -0.3, -0.2, -0.1],
        "Y2": [-0.5, -0.4, -0.3, -0.2, -0.1],
    }
    df = pd.DataFrame(data)
    fig1 = px.scatter(df, x="X1", y="Y1", animation_frame="time")
    fig2 = px.scatter(df, x="X2", y="Y2", animation_frame="time")
    
    # build frames to be animated from two source figures.
    frames = [
        go.Frame(data=f.data + fig1.frames[i].data, name=f.name)
        for i, f in enumerate(fig2.frames)
    ]
    
    combined_fig = go.Figure(data=frames[0].data, frames=frames, layout=fig1.layout)
    combined_fig.show()