dcc.仅在首次加载时加载 (Python)

use*_*606 4 python exception loading choropleth plotly-dash

我正在开发一个 Plotly Dash 项目,该项目有很多经过过滤、切片和切块的分区统计图。这些是相当昂贵的计算,会减慢一切速度,所以我认为作为一个很好的接触,我可以在地图周围添加一个 dcc.loading 包装器,至少让用户知道它正在加载,而不是我的仪表板出现滞后的外观。

我遇到的问题是,地图每次更改后都会出现加载图标。即使是不到 1 秒的快速更改,也会出现加载图标。我的挑战是我仍然想使用 dcc.loading 包装器,但让它仅显示在地图的初始加载上。

我正在 Plotly 社区网站上阅读这个解决相同问题的博客,但没有人能够提出解决方案: https: //community.plotly.com/t/loading-states-and-loading-component /19650/35。此外,我正在尝试使用 Dash 帮助页面中的“PreventUpdate”参数: https: //dash.plotly.com/advanced-callbacks,但仍然找不到解决方案。

谁能帮我指出正确的方向?

这是一些示例代码:

import pandas as pd
import dash
from urllib.request import urlopen
import json
import plotly.express as px
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output 
#from dash.exceptions import PreventUpdate


with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv",
                   dtype={"fips": str})

fips_choices = df['fips'].sort_values().unique()


app = dash.Dash(__name__)
server = app.server
app.layout = html.Div([
    dcc.Dropdown(id='dropdown1',
                 options=[{'label': i, 'value': i} for i in fips_choices],
                 value=fips_choices[0]
    ),
    dcc.Loading(
        id='loading',
        children=[
            dcc.Graph(id='us_map')
    ])
])



@app.callback(
    Output('us_map','figure'),
    Input('dropdown1','value'))

def update_map(county_select):
        new_df = df[df['fips']==county_select]
        fig = px.choropleth_mapbox(new_df, geojson=counties, locations='fips', color='unemp',
                           color_continuous_scale="Viridis",
                           range_color=(0, 12),
                           mapbox_style="carto-positron",
                           zoom=3, center = {"lat": 37.0902, "lon": -95.7129},
                           opacity=0.5
                          )
        fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

        return fig

app.run_server(host='0.0.0.0',port='8051')
Run Code Online (Sandbox Code Playgroud)

小智 5

解决方案如您链接的线程和 redxman 的最后一段所述,但需要一些额外的调整。

使用父 div 并将 dcc.Loading 组件和内容 div 作为同级组件。

html.Div([dcc.Graph(id='us_map'),
          dcc.Loading(id='loading')])
...
Run Code Online (Sandbox Code Playgroud)

dcc.Loading 不仅生成一个 div,还为其自身生成一个父 div。幸运的是,我们可以通过在回调输出中使用“parent_style”属性来访问它。

@app.callback(
    [Output('us_map','figure'),
    Output('loading', 'parent_style')],
    Input('dropdown1','value')
)
def update_map(county_select):
...
  return fig, {'display' : 'none'}
Run Code Online (Sandbox Code Playgroud)

然后您可以正确定位加载动画。此实现的优点之一是能够保持 dcc.Loading 和地图的交互性。

import pandas as pd
import dash
from urllib.request import urlopen
import json
import plotly.express as px
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv",
                   dtype={"fips": str})

fips_choices = df['fips'].sort_values().unique()

loading_style = {'position': 'absolute', 'align-self': 'center'}

app = dash.Dash(__name__)
server = app.server
app.layout = html.Div([
    dcc.Dropdown(id='dropdown1',
                 options=[{'label': i, 'value': i} for i in fips_choices],
                 value=fips_choices[0]
    ),
    html.Div([dcc.Graph(id='us_map', style={'flex-grow': '1'}),
              dcc.Loading(id='loading', parent_style=loading_style)
              ], style= {'position': 'relative', 'display': 'flex', 'justify-content': 'center'}
    )
])


@app.callback(
    [Output('us_map','figure'),
    Output('loading', 'parent_style')
     ],
    Input('dropdown1','value')
)
def update_map(county_select):
        new_loading_style = loading_style
        # Initial load only
        # new_loading_style['display'] = 'none'
        new_df = df[df['fips']==county_select]
        fig = px.choropleth_mapbox(new_df, geojson=counties, locations='fips', color='unemp',
                           color_continuous_scale="Viridis",
                           range_color=(0, 12),
                           mapbox_style="carto-positron",
                           zoom=3, center = {"lat": 37.0902, "lon": -95.7129},
                           opacity=0.5
                          )
        fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

        return fig, new_loading_style

app.run_server(host='0.0.0.0',port='8051')
Run Code Online (Sandbox Code Playgroud)