Как добавить анимацию к сюжетной фигуре в Python

0

Вопрос

В настоящее время у меня есть этот код:

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

График предназначен для построения прямоугольников с использованием полигонов. Скорее всего, не самый эффективный, но и там он открыт для улучшений.

Мой вопрос в том, как добавить анимацию к существующей сюжетной фигуре? В моем df у меня есть столбец времени, который подходит для этого (df.Time). Когда анимация будет добавлена, я хочу нарисовать полигоны только для этой метки времени.

Текущий сюжет без анимации

РЕДАКТИРОВАТЬ: Добавление структуры данных

Так что это не работает при построении графика, как я объясняю в своем комментарии ниже. Однако, если я перейду на сортировку по 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
animation pandas plot plotly
2021-11-22 14:07:05
1

Лучший ответ

1

Вы не предоставили примерные данные. Неявно вы определяете фрейм данных

Полигон Объект Класс объектов время
МНОГОУГОЛЬНИК ((58 91, 58 77, 0 73, -0 87, 58 91)) 0 1 00:00
МНОГОУГОЛЬНИК ((51 102, 58 90, 7 62, 0 74, 51 102)) 0 1 01:00
МНОГОУГОЛЬНИК ((40 110, 52 101, 18 54, 6 63, 40 110)) 0 1 02:00

Это предполагает наличие дополнительного столбца ObjectId, который является одним и тем же полигоном, имеющим разные координаты для каждого времени

Самый простой способ создать сюжетно анимированную фигуру-использовать Plotly Express. Следовательно, реструктурируйте данные, чтобы они были последовательностями x и y в длинном кадре данных

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")

enter image description here

использование выборочных данных

  • примерные данные не используют стройные https://shapely.readthedocs.io/en/stable/manual.html#polygons Следовательно, использование exterior.xy в примере кода это не имеет значения
  • пример данных определяет данные как последовательность значений для ObjId, в которой вершина определяется углом
  • чтобы нарисовать многоугольник, требуется последовательность x/y, включающая одну и ту же точку в начале и в конце. Это было вставлено
  • порядок важен, поэтому определите угол как https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Categorical.html
  • тогда его просто использовать сюжетно для создания анимированной фигуры
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()]},
)
2021-12-03 15:41:12

Большое вам спасибо за ваш ответ! Очень помогайте меду! Однако теперь у меня появилась новая проблема. Используя ваш пример, я перестроил свой фрейм данных в длинный формат с "Широкими" и "Длинными" столбцами. Однако это кажется очень придирчивым к тому, как я сортирую свои данные. Если я отсортирую по "ObjId", это сработает, но временная шкала полностью перепутана. Если вместо этого я отсортирую по "Времени", временная шкала будет в порядке, но тогда она отображает только один объект за значение времени, даже если их несколько.
MartinCB

вы не поделились своей структурой данных, поэтому мне пришлось сделать вывод. Похоже, у вас есть фрейм данных с полигонами, где каждый полигон имеет ObjId, который постоянен во времени / преобразованиях. следовательно, именно так я структурировал данные выборки. обновите свой вопрос с помощью head(10) вашего фрейма данных, и я обновлю его. Вот почему все рекомендации SO по заданию вопросов подчеркивают необходимость обмена образцами данных. Не делайте ужасной вещи-не делитесь своими данными в виде изображения, заставляя любого ответчика использовать ненадежное распознавание для их использования
Rob Raymond

Добавлена моя структура данных выше. Выглядит немного ужасно, но я надеюсь, что вы сможете скопировать его без особых хлопот.
MartinCB

обновленный ответ - вы полностью бросили меня с образцом кода, используя shapely. Похоже, что ваш пример кода и примеры данных не связаны
Rob Raymond

Хе-хе, это потому, что я изменил свой стройный полигональный подход, чтобы он ближе соответствовал вашему ответу. Исходные данные действительно включают полигональные объекты, но я отбросил их, пытаясь адаптировать свой df к вашему примеру.
MartinCB

хорошо - я думаю, что лучше оставить как полигоны... это будет поддерживать сторонние полигоны 3,4,5 и т.д. ключ в том, чтобы отсортировать его, прежде чем взрывать
Rob Raymond

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................