Python 如何使Plotly动画更平滑?

Python 如何使Plotly动画更平滑?,python,animation,plotly-dash,Python,Animation,Plotly Dash,我使用dcc.Interval、dcc.Graph和dcc.Slider创建了一个散点贴图盒动画,而不是使用plotly动画(使用animation\u frame和animation\u group)。这是因为我希望在动画的每个间隔以及用户暂停动画的任何时候都返回滑块的当前值。我找不到从plotly动画中检索滑块当前值的方法 用户将需要单击播放按钮以启用dcc.Interval,滑块将每隔一段时间更改其值。当滑块的值更改时,图形将相应地更新 在下面的代码中,它在渲染每一帧时都投入了大量的工作,

我使用dcc.Interval、dcc.Graph和dcc.Slider创建了一个散点贴图盒动画,而不是使用plotly动画(使用animation\u frame和animation\u group)。这是因为我希望在动画的每个间隔以及用户暂停动画的任何时候都返回滑块的当前值。我找不到从plotly动画中检索滑块当前值的方法

用户将需要单击播放按钮以启用dcc.Interval,滑块将每隔一段时间更改其值。当滑块的值更改时,图形将相应地更新

在下面的代码中,它在渲染每一帧时都投入了大量的工作,因为“update\u figure”回调做了大量的工作,每次滑块的值发生变化时都会将大量数据返回到dcc.Graph

有没有办法在开始时将所有数据加载到图形中,并在滑块值更改时切换帧

导入破折号
将仪表板核心组件作为dcc导入
将dash_html_组件导入为html
从dash.dependencies导入输入、输出和状态
从dash.exceptions导入预防更新
将numpy作为np导入
作为pd进口熊猫
导入plotly.graph_objs作为go
app=dash.dash(_名称__)
def set_滑块_日历(数据帧):
日历=[]
对于范围(0,dataframe.shape[0])中的i:
值=数据帧[i],如果i%7==0,则为其他“”
calendar.append(值)
返回日历
访问\u令牌='mapbox\u令牌'
数据https://shahinrostami.com/datasets/time-series-19-covid-combined.csv'
数据=pd.read\u csv(数据url)
缺少_states=pd.isnull(数据['Province/State'])
data.loc[缺失州,'省/州']=data.loc[缺失州,'国家/地区']
数据['Active']=数据['Confirmed']-数据['Recovered']-数据['Death']
对于范围(0,data.shape[0])中的i:
data.loc[i,‘Size']=data.loc[i,‘Active']如果data.loc[i,‘Active']<50,则为50
data=data.dropna()
df_date=data['date'].unique()
app.layout=html.Div([
dcc.间隔(
id='interval',
间隔=2000,
n_间隔=0,
最大间隔=df_日期形状[0]-1,
禁用=真
),
dcc.Graph(id='my_Graph'),
滑块(
id='slider',
最小值=0,
max=df_日期形状[0]-1,
值=0,
marks={str(i):str(des)for i,des in zip(范围(0,df_date.shape[0]),set_slider_calendar(df_date)),
点=真
),
Div(id='label',style={'margin-top':20}),
按钮('Play',id='my_btn'),
])
@app.callback([输出('interval','disabled'),输出('my_btn','children')],
[输入('my_btn','n_clicks'),
[状态('interval','disabled'))
def显示值(单击,值):
打印('单击',值)
如果单击:
新值=非值
btn_name='Play'如果是新值,则为'Pause'
返回新的\u值,btn\u名称
其他:
提出预防性更新
@app.callback(输出('label','children'),
[输入('滑块','值')])
def显示_值(值):
返回“所选日历:{df_日期[值]}”
@应用程序回调(输出('slider','value'),
[输入('interval','n_interval'))
def update_滑块(数值):
返回数
@app.callback(
输出('my_graph','figure'),
[输入('滑块','值')])
def更新图(所选年份):
过滤的日期=数据[数据['Date']==日期[所选的年份]]
跟踪=[]
对于已过滤的_df['Province/State']中的i.unique():
df_by_大陆=过滤的_df[过滤的_df['省/州]==i]
traces.append(
去吧,扫瞄机(
lat=df_按_大陆['lat'],
lon=df_按_大陆['Long'],
mode='markers',
marker=go.scattermapbox.marker(
大小=按大陆划分的df大小['size']
),
text=df_按大陆[“省/州”],
)
)
返回{
“数据”:跟踪,
“布局”:dict(
autosize=True,
hovermode='closest',
mapbox=dict(
accesstoken=访问令牌,
轴承=0,
中心=听写(
lat=38.92,
lon=-77.07
),
螺距=0,
缩放=1
),
过渡={
“持续时间”:500,
“宽松”:“立方输入输出”
}
)
}
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
app.run_服务器(debug=True)
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate

import numpy as np
import pandas as pd
import plotly.graph_objs as go

app = dash.Dash(__name__)


def set_slider_calendar(dataframe):
    calendar = []
    for i in range(0, dataframe.shape[0]):
        value = dataframe[i] if i % 7 == 0 else ''
        calendar.append(value)
    return calendar


access_token = 'mapbox_token'
data_url = 'https://shahinrostami.com/datasets/time-series-19-covid-combined.csv'
data = pd.read_csv(data_url)
missing_states = pd.isnull(data['Province/State'])
data.loc[missing_states, 'Province/State'] = data.loc[missing_states, 'Country/Region']
data['Active'] = data['Confirmed'] - data['Recovered'] - data['Deaths']
for i in range(0, data.shape[0]):
    data.loc[i, 'Size'] = data.loc[i, 'Active'] if data.loc[i, 'Active'] < 50 else 50
data = data.dropna()
df_date = data['Date'].unique()

app.layout = html.Div([
    dcc.Interval(
        id='interval',
        interval=2000,
        n_intervals=0,
        max_intervals=df_date.shape[0] - 1,
        disabled=True
    ),
    dcc.Graph(id='my_graph'),
    dcc.Slider(
        id='slider',
        min=0,
        max=df_date.shape[0] - 1,
        value=0,
        marks={str(i): str(des) for i, des in zip(range(0, df_date.shape[0]), set_slider_calendar(df_date))},
        dots=True
    ),
    html.Div(id='label', style={'margin-top': 20}),
    html.Button('Play', id='my_btn'),
])


@app.callback([Output('interval', 'disabled'), Output('my_btn', 'children')],
              [Input('my_btn', 'n_clicks')],
              [State('interval', 'disabled')])
def display_value(click, value):
    print('click', value)
    if click:
        new_value = not value
        btn_name = 'Play' if new_value else 'Pause'
        return new_value, btn_name
    else:
        raise PreventUpdate


@app.callback(Output('label', 'children'),
              [Input('slider', 'value')])
def display_value(value):
    return f'Selected Calendar: {df_date[value]} '


@app.callback(Output('slider', 'value'),
              [Input('interval', 'n_intervals')])
def update_slider(num):
    return num


@app.callback(
    Output('my_graph', 'figure'),
    [Input('slider', 'value')])
def update_figure(selected_year):
    filtered_df = data[data['Date'] == df_date[selected_year]]
    traces = []
    for i in filtered_df['Province/State'].unique():
        df_by_continent = filtered_df[filtered_df['Province/State'] == i]
        traces.append(
            go.Scattermapbox(
                lat=df_by_continent['Lat'],
                lon=df_by_continent['Long'],
                mode='markers',
                marker=go.scattermapbox.Marker(
                    size=df_by_continent['Size']
                ),
                text=df_by_continent['Province/State'],

            )
        )

    return {
        'data': traces,
        'layout': dict(
            autosize=True,
            hovermode='closest',
            mapbox=dict(
                accesstoken=access_token,
                bearing=0,
                center=dict(
                    lat=38.92,
                    lon=-77.07
                ),
                pitch=0,
                zoom=1
            ),
            transition={
                'duration': 500,
                'easing': 'cubic-in-out'
            }
        )
    }


if __name__ == '__main__':
    app.run_server(debug=True)