【问题标题】:How to add animation to plotly figure in Python如何在Python中添加动画以绘制图形
【发布时间】:2022-01-01 03:08:10
【问题描述】:

目前我有这个代码:

fig= go.Figure()
for idx in range(len(reference)):
    df = reference.loc[idx]
    if df.ObjClass != 0:
        x,y = df.Polygon.exterior.xy
        fig.add_trace(go.Scatter(x=np.array(x), y=np.array(y)))
return fig

该图用于使用多边形的边界框。最有可能不是最有效的,也有待改进。

我的问题是如何向现有的 Plotly 人物添加动画?在我的 df 中,我有一个适合该时间的时间列(df.Time)。添加动画后,我只想绘制该时间戳的多边形。

Current plot without animation

编辑:添加数据结构

所以这在绘图时不起作用,正如我在下面的评论中解释的那样。但是,如果我更改为按 ObjID 而不是时间排序,它确实有效,但动画帧未排序。我希望最低的时间排在第一位,时间最高的排在最后。

ObjClass    Time    ObjID   Corner  Lat Long
0   3.0 5.9 54.0    RR  21.549906   129.418088
563 3.0 5.9 54.0    LR  23.569243   129.523022
1126    3.0 5.9 54.0    LF  23.569243   136.523022
1689    3.0 5.9 54.0    RF  21.549906   136.418088
1   3.0 5.95    54.0    RR  17.946687   114.856340
564 3.0 5.95    54.0    LR  19.726662   114.919184
1127    3.0 5.95    54.0    LF  19.726662   121.919184
1690    3.0 5.95    54.0    RF  17.946687   121.856340
2   3.0 6.0 54.0    RR  17.685873   121.115523
565 3.0 6.0 54.0    LR  19.556310   121.182149
1128    3.0 6.0 54.0    LF  19.556310   128.182149
1691    3.0 6.0 54.0    RF  17.685873   128.115523
3   3.0 6.05    54.0    RR  17.685873   121.115523
566 3.0 6.05    54.0    LR  19.556310   121.182149
1129    3.0 6.05    54.0    LF  19.556310   128.182149
1692    3.0 6.05    54.0    RF  17.685873   128.115523
4   3.0 6.1 54.0    RR  17.375609   127.925362
567 3.0 6.1 54.0    LR  19.322351   127.848100
1130    3.0 6.1 54.0    LF  19.322351   134.848100
1693    3.0 6.1 54.0    RF  17.375609   134.925362

【问题讨论】:

    标签: python pandas animation plot plotly


    【解决方案1】:

    您没有提供样本数据。隐式定义了一个数据框

    Polygon ObjectId ObjClass time
    POLYGON ((58 91, 58 77, 0 73, -0 87, 58 91)) 0 1 00:00
    POLYGON ((51 102, 58 90, 7 62, 0 74, 51 102)) 0 1 01:00
    POLYGON ((40 110, 52 101, 18 54, 6 63, 40 110)) 0 1 02:00

    这假定了一个附加列 ObjectId,它是相同的 多边形,每个 时间

    具有不同的坐标

    创建 plotly 动画人物的最简单方法是使用 Plotly Express。因此,将数据重组为长数据帧中的 xy 序列

    import io
    import pandas as pd
    import numpy as np
    import plotly.graph_objects as go
    import plotly.express as px
    import shapely.wkt
    
    
    df_p = pd.read_csv(io.StringIO("""Polygon,ObjectId,ObjClass,time
    "POLYGON ((58 91, 58 77, 0 73, -0 87, 58 91))",0,1,00:00
    "POLYGON ((51 102, 58 90, 7 62, 0 74, 51 102))",0,1,01:00
    "POLYGON ((40 110, 52 101, 18 54, 6 63, 40 110))",0,1,02:00
    "POLYGON ((28 112, 41 109, 30 52, 17 55, 28 112))",0,1,03:00
    "POLYGON ((32 29, 20 33, 38 93, 50 89, 32 29))",1,1,00:00
    "POLYGON ((45 31, 34 29, 25 91, 36 93, 45 31))",1,1,01:00
    "POLYGON ((57 38, 47 32, 13 84, 23 90, 57 38))",1,1,02:00
    "POLYGON ((65 50, 58 39, 5 72, 12 83, 65 50))",1,1,03:00
    "POLYGON ((1 90, 7 90, 12 48, 6 48, 1 90))",2,1,00:00
    "POLYGON ((-7 85, -2 89, 20 53, 15 49, -7 85))",2,1,01:00
    "POLYGON ((-13 78, -10 83, 26 60, 23 55, -13 78))",2,1,02:00
    "POLYGON ((-15 69, -14 75, 28 69, 27 63, -15 69))",2,1,03:00
    "POLYGON ((59 12, 49 18, 84 92, 94 86, 59 12))",3,1,00:00
    "POLYGON ((77 11, 65 11, 66 93, 78 93, 77 11))",3,1,01:00
    "POLYGON ((94 17, 83 12, 49 87, 60 92, 94 17))",3,1,02:00
    "POLYGON ((107 30, 99 21, 36 74, 44 83, 107 30))",3,1,03:00
    "POLYGON ((9 29, 3 37, 13 43, 19 35, 9 29))",4,1,00:00
    "POLYGON ((12 28, 4 34, 10 44, 18 38, 12 28))",4,1,01:00
    "POLYGON ((15 29, 5 31, 7 43, 17 41, 15 29))",4,1,02:00
    "POLYGON ((17 32, 8 29, 5 40, 14 43, 17 32))",4,1,03:00"""))
    
    df_p["Polygon"] = df_p["Polygon"].apply(shapely.wkt.loads)
    
    # explode out ploygons to x & y for plotly express
    df_plot = (
        df_p["Polygon"]
        .apply(
            lambda p: [{"x": x, "y": y} for x, y in zip(p.exterior.xy[0], p.exterior.xy[1])]
        )
        .explode()
        .apply(pd.Series)
        .join(df_p)
    )
    
    
    px.line(df_plot, x="x", y="y", color="ObjectId", animation_frame="time")
    

    使用样本数据

    import pandas as pd
    import io
    import plotly.express as px
    
    df = pd.read_csv(
        io.StringIO(
            """ObjClass    Time    ObjID   Corner  Lat Long
    0   3.0 5.9 54.0    RR  21.549906   129.418088
    563 3.0 5.9 54.0    LR  23.569243   129.523022
    1126    3.0 5.9 54.0    LF  23.569243   136.523022
    1689    3.0 5.9 54.0    RF  21.549906   136.418088
    1   3.0 5.95    54.0    RR  17.946687   114.856340
    564 3.0 5.95    54.0    LR  19.726662   114.919184
    1127    3.0 5.95    54.0    LF  19.726662   121.919184
    1690    3.0 5.95    54.0    RF  17.946687   121.856340
    2   3.0 6.0 54.0    RR  17.685873   121.115523
    565 3.0 6.0 54.0    LR  19.556310   121.182149
    1128    3.0 6.0 54.0    LF  19.556310   128.182149
    1691    3.0 6.0 54.0    RF  17.685873   128.115523
    3   3.0 6.05    54.0    RR  17.685873   121.115523
    566 3.0 6.05    54.0    LR  19.556310   121.182149
    1129    3.0 6.05    54.0    LF  19.556310   128.182149
    1692    3.0 6.05    54.0    RF  17.685873   128.115523
    4   3.0 6.1 54.0    RR  17.375609   127.925362
    567 3.0 6.1 54.0    LR  19.322351   127.848100
    1130    3.0 6.1 54.0    LF  19.322351   134.848100
    1693    3.0 6.1 54.0    RF  17.375609   134.925362"""
        ),
        sep="\s+",
        engine="python",
    )
    
    # if polygon is a quadrangle, need five points to define it. 4 is just a linestring
    # duplicate first corner
    df = pd.concat([df, df.loc[df["Corner"].eq("RR")].assign(Corner="RR2")])
    
    # need to sort by Corner, hence make it a categorical
    df["Corner"] = pd.Categorical(
        df["Corner"], ["RR", "RF", "LF", "LR", "RR2"], ordered=True
    )
    
    px.line(
        df.sort_values(["ObjID", "Time", "Corner"]),
        x="Long",
        y="Lat",
        color="ObjID",
        animation_frame="Time",
    ).update_layout(
        xaxis={"range": [df["Long"].min(), df["Long"].max()]},
        yaxis={"range": [df["Lat"].min(), df["Lat"].max()]},
    )
    

    【讨论】:

    • 非常感谢您的回答!帮了大忙!但是现在我有一个新问题。使用您的示例,我将数据框重组为带有“Lat”和“Long”列的长格式。但是,我对数据的排序方式似乎非常挑剔。如果我按“ObjID”排序,它可以工作,但时间线全乱了。如果我改为按“时间”排序,则时间线没问题,但它只绘制每个时间值的对象之一,即使有多个。
    • 你没有共享你的数据结构,所以我不得不推断它。看起来您有一个带有多边形的数据框,其中每个多边形都有一个 ObjId,该 ObjId 在时间/转换中是恒定的。因此,这就是我构建样本数据的方式。用你的数据框的head(10) 更新你的问题,我会更新。这就是为什么所有关于提问的 SO 指南都强调需要共享样本数据。不要做可怕的事情,将您的数据共享为图像,迫使任何回答者使用不可靠的 OCR 来使用它
    • 在上面添加了我的数据结构。看起来有点可怕,但我希望你能轻松复制它。
    • 更新了答案 - 你用 shapely 的示例代码完全把我扔给了我。您的示例代码和示例数据似乎不相关
    • 呵呵,那是因为我改变了我的 Shapely Polygon 方法以更接近您的答案。原始数据确实包含 Polygon 对象,但在尝试使我的 df 适应您的示例时,我删除了这些对象。
    猜你喜欢
    • 2021-10-10
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多