dcc.Loading 仅在第一次加载时 (Python)
dcc.Loading on First Load Only (Python)
我正在做一个 Plotly Dash 项目,它有很多经过过滤、切片和切块的等值线图。这些是非常昂贵的计算,会减慢一切,所以我认为作为一个很好的接触,我可以在地图周围添加一个 dcc.loading 包装器,至少让用户知道它正在加载,而不是我的仪表板看起来滞后.
我遇到的问题是每次地图更改后都会出现加载图标。即使是不到 1 秒的快速更改,加载图标也会出现。我的挑战是我仍想使用 dcc.loading 包装器,但只在地图的初始加载时显示它。
我正在阅读 Plotly 社区网站上的这篇博客,它解决了同样的问题,但没有人能够提出解决方案:https://community.plotly.com/t/loading-states-and-loading-component/19650/35. Further, I was playing around with the "PreventUpdate" argument from the Dash help page here: 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')
dcc.Loading
可能没有办法
这是一个对我有用的解决方案。
为您的地图设置 {"display":"none"}
样式
dcc.Graph(id="us_map", style={"display": "none"})
在回调中添加 us-map 样式作为输出和 return {"display":"inline"}
@app.callback(
[Output("us_map", "figure"), Output("us_map", "style")], 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, {"display": "inline"}
如果你想要加载栏而不是空白区域,请将加载栏放在地图上方的 div 中,将加载栏作为输出添加到 div,添加一个return of {"display":"false"} 以便在地图加载时加载动画消失。你不能让它与 dcc.Loading 一起工作,所以我只是使用了一个自定义的 CSS 加载栏。
解决方案如 described in the thread you linked 和 redxman 的最后一段,但需要一些额外的调整。
使用父级 div 并将 dcc.Loading 组件和内容 div 作为同级。
html.Div([dcc.Graph(id='us_map'),
dcc.Loading(id='loading')])
...
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'}
然后您就可以正确定位加载动画了。此实现的一个优点是能够保持 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')
我正在做一个 Plotly Dash 项目,它有很多经过过滤、切片和切块的等值线图。这些是非常昂贵的计算,会减慢一切,所以我认为作为一个很好的接触,我可以在地图周围添加一个 dcc.loading 包装器,至少让用户知道它正在加载,而不是我的仪表板看起来滞后.
我遇到的问题是每次地图更改后都会出现加载图标。即使是不到 1 秒的快速更改,加载图标也会出现。我的挑战是我仍想使用 dcc.loading 包装器,但只在地图的初始加载时显示它。
我正在阅读 Plotly 社区网站上的这篇博客,它解决了同样的问题,但没有人能够提出解决方案:https://community.plotly.com/t/loading-states-and-loading-component/19650/35. Further, I was playing around with the "PreventUpdate" argument from the Dash help page here: 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')
dcc.Loading
可能没有办法这是一个对我有用的解决方案。
为您的地图设置 {"display":"none"}
样式dcc.Graph(id="us_map", style={"display": "none"})
在回调中添加 us-map 样式作为输出和 return {"display":"inline"}
@app.callback(
[Output("us_map", "figure"), Output("us_map", "style")], 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, {"display": "inline"}
如果你想要加载栏而不是空白区域,请将加载栏放在地图上方的 div 中,将加载栏作为输出添加到 div,添加一个return of {"display":"false"} 以便在地图加载时加载动画消失。你不能让它与 dcc.Loading 一起工作,所以我只是使用了一个自定义的 CSS 加载栏。
解决方案如 described in the thread you linked 和 redxman 的最后一段,但需要一些额外的调整。
使用父级 div 并将 dcc.Loading 组件和内容 div 作为同级。
html.Div([dcc.Graph(id='us_map'),
dcc.Loading(id='loading')])
...
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'}
然后您就可以正确定位加载动画了。此实现的一个优点是能够保持 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')