【发布时间】:2020-09-30 00:32:06
【问题描述】:
我正在尝试创建一个 Dash 仪表板,其中一个框中的下拉选项取决于之前的下拉选择。
数据由两个字典组成,每个字典有两个键。每个键都包含一个带有几列的数据框。具体数据:
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import numpy as np
from plotly.subplots import make_subplots
import plotly.express as px
import pandas as pd
from pandas import Timestamp
import numpy as np
df_vals_prod={'corn':pd.DataFrame({'time': {1: Timestamp('2020-09-23 06:00:00'),
2: Timestamp('2020-09-23 12:00:00'),
3: Timestamp('2020-09-23 18:00:00'),
4: Timestamp('2020-09-24 00:00:00')},
'2m_temp_prod': {1: 0.020584322444347606,
2: 0.08973907730395358,
3: 2.3866310395722463,
4: 3.065472457668321},
'total_precip_prod': {1: 1.372708470272411,
2: 2.135683294556938,
3: 1.9811172016307312,
4: 2.1082116841869323}}),
'soybeans':pd.DataFrame({'time': {1: Timestamp('2020-09-23 06:00:00'),
2: Timestamp('2020-09-23 12:00:00'),
3: Timestamp('2020-09-23 18:00:00'),
4: Timestamp('2020-09-24 00:00:00')},
'2m_temp_prod': {1: 0.6989001827317545,
2: -0.8699121426411993,
3: -0.9484359259520706,
4: 0.7391299158393124},
'total_precip_prod': {1: -0.07639291299336869,
2: 0.19182892415959496,
3: 0.8719339093510236,
4: 0.90586956349059}})}
df_vals_area={'corn':pd.DataFrame({'time': {1: Timestamp('2020-09-23 06:00:00'),
2: Timestamp('2020-09-23 12:00:00'),
3: Timestamp('2020-09-23 18:00:00'),
4: Timestamp('2020-09-24 00:00:00')},
'2m_temp_area': {1: -1.6820417878457192,
2: -0.2856437053872421,
3: 0.3864022581278122,
4: 0.5873739667356371},
'total_precip_area': {1: 1.3703311242708185,
2: 0.25528434511264525,
3: 0.5007488191835624,
4: -0.16292114222272375}}),
'soybeans':pd.DataFrame({'time': {1: Timestamp('2020-09-23 06:00:00'),
2: Timestamp('2020-09-23 12:00:00'),
3: Timestamp('2020-09-23 18:00:00'),
4: Timestamp('2020-09-24 00:00:00')},
'2m_temp_area': {1: 1.3789989862086967,
2: -0.7797086923820608,
3: 1.0695635889750523,
4: 1.136561500804678},
'total_precip_area': {1: -0.6035111830104833,
2: -0.18237330469451313,
3: -0.7820158376898607,
4: -0.6117188028872137}})}
app = JupyterDash(external_stylesheets=[dbc.themes.SLATE])
weight_opts=['Production','Area']
controls = dbc.Card(
[ dbc.FormGroup(
[
dbc.Label("Crop"),
dcc.Dropdown(
id="Crop",
options=[
{"label": col, "value": col} for col in list(df_vals_prod.keys())
],
value=list(df_vals_prod.keys())[0],
clearable=False,
),
]
),
dbc.FormGroup(
[
dbc.Label("Weighting"),
dcc.Dropdown(
id="weights",
options=[
{"label": i, "value": i} for i in weight_opts
],
value=weight_opts[0],
clearable=False,
),
]
),
dbc.FormGroup(
[
dbc.Label("Forecast Variable"),
dcc.Dropdown(
id="forecast_v",
),
]
),
],
body=True,
)
app.layout = dbc.Container(
[
html.Hr(),
dbc.Row([
dbc.Col([
dbc.Row([
dbc.Col(controls)
], align="start"),
dbc.Row([
dbc.Col([
html.Br(),
dbc.Row([
dbc.Col([html.Div(id = 'txt1')
])
]),
html.Br(),
dbc.Row([
dbc.Col([html.Div(id = 'txt2')])
])
])
])
],xs = 2)
,
dbc.Col([
dbc.Row([
dbc.Col([html.Div(id = 'plot_title')],)
]),
dbc.Row([
dbc.Col(dcc.Graph(id="crop-graph")),
#dbc.Col(dcc.Graph(id="cluster-graph"))
])
])
],),
],
fluid=True,
)
@app.callback(
Output('forecast_v','options'),
[Input('weights', 'value')]
)
def update_var_dropdown(weight):
if weight=='Production':
return [{'label': i, 'value': i} for i in df_vals_prod['corn'].columns[1:]]
elif weight=='Area':
return [{'label': i, 'value': i} for i in df_vals_area['corn'].columns[1:]]
@app.callback(
Output("crop-graph", "figure"),
[ Input("Crop", "value"),
Input("weights", "value"),
Input("forecast_v", "value"),
],
)
def crop_graph(Crop, val, weight):
# plotly figure setup
fig = make_subplots(specs=[[{"secondary_y": True}]])
if weight:
fig.add_trace(go.Scatter(name=val, x=df_vals_prod[Crop]['time'], y=((df_vals_prod[Crop][val]-273)*(9/5))+32, mode = 'lines', line=dict(color='red', width=4),
hovertemplate='Date: %{x|%d %b %H%M} UTC<br>Temp: %{y:.2f} F<extra></extra>'), secondary_y=False,
)
fig.update_yaxes(title_text="<b>Temp (F)<b>", color='red', secondary_y=False,)
fig.update_yaxes(title_text="<b>24hr Forecast Change (F)</b>", secondary_y=True)
return(fig)
app.run_server(mode='external', port = 8099)
如您所见,此 6 小时数据旨在绘制为时间序列。现在我想添加几个下拉菜单。第一个下拉菜单 (Crop) 选择要选择的作物(玉米或大豆),这是每个字典中的两个键。
第二个下拉菜单(权重)现在选择我们要使用的数据框。用户在第二个下拉列表中选择的内容将决定在第三个下拉列表中选择的选项。
第三个下拉菜单将选择实际变量(预测变量),它是每个数据帧中可用的两列之一。因此,如果在下拉菜单 2 中选择了“生产”,则下拉菜单 3 的选项将由“2m_temp_prod”或“total_precip_prod”组成。对于下拉菜单 2 中的“区域”,下拉菜单 3 选项将为“2m_temp_area”或“total_precip_area”。
这是我到目前为止的代码。我能够为下拉菜单正确设置回调,但我认为我的第二个回调不能正常工作。我了解如何创建动态下拉列表,但我不确定如何将其转化为实际绘制数据。
这产生了这个情节。请注意,下拉列表是我想要的,但它没有绘制。如何添加“权重”以制作所需的情节?我所期望的只是一个简单的折线图,其中数据取决于所选的所有下拉菜单。
编辑:正如vestland 所建议的,我包含的数据样本要小得多。在这种情况下,具体的值无关紧要,只是数据的结构。更简洁的数据见上文。
【问题讨论】:
-
您能否提供一个完整的代码 sn-p 以及您的数据样本和导入?
标签: python plotly plotly-dash