Reputation: 101
I am trying to make an interactive plot where a user would select a location, then a time, and then one of a list of parameters. I am able to plot a basic plot of each parameter, but what I want to do is that when multiple parameters from the list are selected, a stacked subplot begins to form for each parameter. I have what I thought was a loop that is correct, but it doesn't seem to run through it to make the subplots.
Looking for some help on how to do add subplots under the conditions of more than one parameter selected.
Code below:
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output, State
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
import glob
import os
import plotly.subplots as sp
pd.options.mode.chained_assignment = None
path = r'C:\path'
all_files = glob.glob(os.path.join(path, "*.csv"))
print(all_files)
#create list of columns for pd.read_table
col_list = list(range(0, 24))
df = pd.concat(map(pd.read_csv, all_files))
df['run_time'] = pd.to_datetime(df['run_time'])
df['forecast_time'] = pd.to_datetime(df['forecast_time'])
df['r_hour'] = df['run_time'].dt.hour
df = df.astype({'r_hour': str})
# create a list of our conditions
conditions = [
(df['lat'] > 10),
(df['lat'] < 10)
]
# create a list of the values we want to assign for each condition
values = ['k', 'w']
df['location'] = np.select(conditions, values)
df = df.drop(columns=['lat','lon'])
print(df)
#Build App
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Dropdown(
id="location",
options=[{'label': 'K', 'value': 'k'},
{'label': 'W', 'value': 'w'}],
value="location",
placeholder='Select a location',
),
dcc.Dropdown(
id="r_hour",
options=[{'label': '00Z', 'value': '0'},
{'label': '06Z', 'value': '6'},
{'label': '12Z', 'value': '12'},
{'label': '18Z', 'value': '18'}],
value="r_hour",
placeholder="Select a forecast time",
),
dcc.Dropdown(
id="parameter",
options=[{"label": x, "value": x} for x in df["parameter"].unique()],
value="param",
placeholder='Select a parameter',
multi=True
),
dcc.Graph(id="graph1", figure={}
),
]
)
print(len(df.parameter.unique()))
dff = df[(df.location=='w') & (df.r_hour=='0') & (df.parameter.isin(['CAPE']))]
print(dff)
@app.callback(
Output("graph1", "figure"),
Input("location", "value"),
Input("r_hour", "value"),
Input('parameter', 'value'),
)
def update_graph1(loc, r_hour, parameter):
if len(loc) == 0:
return dash.no_update
else:
dff = df[(df.location == loc) & (df.r_hour == r_hour) & (df.parameter.isin(parameter))]
print(loc, r_hour, parameter)
print(len(parameter))
print(range(len(parameter)))
if len(parameter) > 1:
fig = sp.make_subplots(rows=(len(parameter)), cols=1)
for n in range(len(parameter)):
print(n)
fig.append_trace(px.scatter(dff, x='forecast_time', y=dff.columns[5:10], row=n, col=1))
else:
print(dff)
fig = px.scatter(dff, x='forecast_time', y=dff.columns[5:10])
return fig
# Run app and display result inline in the notebook
if __name__ == '__main__':
app.run_server(debug=True)
Example of data:
run_time forecast_time parameter mean max min ci_low ci_high r_hour loc
9/14/2016 12:00 9/14/2016 18:00 APCP 0.041483684 0.127401644 0.009763785 0.029901197 0.060754167 12 w
9/14/2016 12:00 9/15/2016 0:00 APCP 0.037159666 0.140004013 0.000519685 0.026262613 0.056544125 12 w
9/14/2016 12:00 9/15/2016 6:00 APCP 0.053111446 0.163689065 0.009968509 0.038685651 0.075773072 12 w
9/14/2016 12:00 9/15/2016 12:00 APCP 0.02625966 0.083563037 0.004811026 0.01951379 0.036598051 12 w
9/14/2016 12:00 9/15/2016 18:00 APCP 0.037727973 0.10328352 0.007964571 0.028584858 0.05144924 12 w
9/14/2016 12:00 9/14/2016 12:00 CAPE 2531.348 2783.08 2364.6 2484.948 2583.0745 12 w
9/14/2016 12:00 9/14/2016 18:00 CAPE 2343.2995 2618.87 1895.03 2240.252 2419.445 12 w
9/14/2016 12:00 9/15/2016 0:00 CAPE 2270.763 2521.38 1965.84 2203.535 2334.4885 12 w
9/14/2016 12:00 9/15/2016 6:00 CAPE 2422.276 2637.64 2000.03 2340.4395 2476.8495 12 w
9/14/2016 12:00 9/15/2016 12:00 CAPE 2560.587 2765.51 2167.7 2484.0775 2621.121 12 w
9/14/2016 12:00 9/15/2016 18:00 CAPE 2434.641 2643.32 2177.51 2375.872 2485.731 12 w
9/14/2016 12:00 9/14/2016 12:00 WSPD 13.67982033 14.92190326 11.93637952 13.28460204 14.01356071 12 w
9/14/2016 12:00 9/14/2016 18:00 WSPD 13.00873562 14.51315919 11.61153561 12.670458 13.35743091 12 w
9/14/2016 12:00 9/15/2016 0:00 WSPD 13.15495082 14.50841618 11.95527281 12.86944934 13.47149018 12 w
9/14/2016 12:00 9/15/2016 6:00 WSPD 12.25102442 13.75337432 10.89424146 11.92889921 12.55852141 12 w
9/14/2016 12:00 9/15/2016 12:00 WSPD 13.61138813 14.97033537 11.80458902 13.27546662 13.8712801 12 w
9/14/2016 12:00 9/15/2016 18:00 WSPD 11.86885821 13.08368289 10.74028982 11.607135 12.14320021 12 w
9/14/2016 18:00 9/15/2016 0:00 APCP 0.034182499 0.079354374 0.003188978 0.025235644 0.044085457 18 w
9/14/2016 18:00 9/15/2016 6:00 APCP 0.046251403 0.144504015 0.006216539 0.034403562 0.064499641 18 w
9/14/2016 18:00 9/15/2016 12:00 APCP 0.029244504 0.23320485 0.005094491 0.016554536 0.07372189 18 w
9/14/2016 18:00 9/15/2016 18:00 APCP 0.024053163 0.087622095 0.002917324 0.016503159 0.03626065 18 w
9/14/2016 18:00 9/14/2016 18:00 CAPE 2435.6345 2712.71 2094.12 2370.4595 2499.1125 18 w
9/14/2016 18:00 9/15/2016 0:00 CAPE 2276.4495 2400.68 2040.39 2231.341 2310.1765 18 w
9/14/2016 18:00 9/15/2016 6:00 CAPE 2443.665 2747.34 2135.22 2382.9555 2505.553 18 w
9/14/2016 18:00 9/15/2016 12:00 CAPE 2499.848 2758.34 2242.96 2442.4635 2557.9475 18 w
9/14/2016 18:00 9/15/2016 18:00 CAPE 2445.8005 2623 2252.07 2392.139 2496.5585 18 w
9/14/2016 18:00 9/14/2016 18:00 WSPD 12.80103404 14.36857011 11.76708975 12.54172344 13.11939702 18 w
9/14/2016 18:00 9/15/2016 0:00 WSPD 13.2089427 15.63134179 11.92824288 12.92959876 13.63760661 18 w
9/14/2016 18:00 9/15/2016 6:00 WSPD 12.72761899 13.52581477 11.74122287 12.46831392 12.95820863 18 w
9/14/2016 18:00 9/15/2016 12:00 WSPD 13.78891527 14.57733477 12.43695412 13.5125545 13.98578588 18 w
9/14/2016 18:00 9/15/2016 18:00 WSPD 11.80539318 12.4321654 10.59583493 11.54830383 11.9986291 18 w
9/14/2016 12:00 9/14/2016 18:00 APCP 0.024927179 0.057874047 0.011023628 0.020621271 0.032037025 12 k
9/14/2016 12:00 9/15/2016 0:00 APCP 0.012142526 0.072992165 0 0.006259058 0.024529935 12 k
9/14/2016 12:00 9/15/2016 6:00 APCP 0.0341449 0.0889843 0.003606301 0.02528151 0.045535458 12 k
9/14/2016 12:00 9/15/2016 12:00 APCP 0.013788196 0.058086646 0.000535433 0.008549217 0.022687808 12 k
9/14/2016 12:00 9/15/2016 18:00 APCP 0.007568902 0.024826785 0.001023623 0.005498428 0.011116148 12 k
9/14/2016 12:00 9/14/2016 12:00 CAPE 1915.985 2022.58 1724.18 1877.471 1944.124 12 k
9/14/2016 12:00 9/14/2016 18:00 CAPE 1765.312 1976.54 1571.52 1723.748 1808.896 12 k
9/14/2016 12:00 9/15/2016 0:00 CAPE 1903.907 2111.48 1630.76 1849.207 1955.516 12 k
9/14/2016 12:00 9/15/2016 6:00 CAPE 2022.187 2218.66 1744.28 1971.346 2066.359 12 k
9/14/2016 12:00 9/15/2016 12:00 CAPE 2117.713 2289.48 1977.74 2080.877 2160.069 12 k
9/14/2016 12:00 9/15/2016 18:00 CAPE 2035.243 2287.06 1737.66 1966.873 2093.823 12 k
9/14/2016 12:00 9/14/2016 12:00 WSPD 11.51403081 12.90299913 9.348005138 11.02996656 11.91310878 12 k
9/14/2016 12:00 9/14/2016 18:00 WSPD 10.66348483 12.10730058 8.536612865 10.2005094 11.04692859 12 k
9/14/2016 12:00 9/15/2016 0:00 WSPD 10.81256637 12.22364593 9.74415303 10.53260001 11.1350116 12 k
9/14/2016 12:00 9/15/2016 6:00 WSPD 11.10226976 12.35115476 9.882793516 10.80288164 11.39107227 12 k
9/14/2016 12:00 9/15/2016 12:00 WSPD 11.26334728 12.6892719 9.999631254 10.97207787 11.57319938 12 k
9/14/2016 12:00 9/15/2016 18:00 WSPD 9.835853253 11.13364239 7.475216637 9.385502624 10.13933703 12 k
9/14/2016 18:00 9/15/2016 0:00 APCP 0.017726388 0.074779568 0.002259844 0.011548038 0.028326 18 k
9/14/2016 18:00 9/15/2016 6:00 APCP 0.027098834 0.054606329 0.001393702 0.020021664 0.0343012 18 k
9/14/2016 18:00 9/15/2016 12:00 APCP 0.020631507 0.119322899 0.002086615 0.010669297 0.0426827 18 k
9/14/2016 18:00 9/15/2016 18:00 APCP 0.005209452 0.012196857 0 0.003969687 0.006824413 18 k
9/14/2016 18:00 9/14/2016 18:00 CAPE 1764.579 1914.96 1525.46 1722.144 1800.189 18 k
9/14/2016 18:00 9/15/2016 0:00 CAPE 1904.978 2052.38 1701.34 1861.194 1941.033 18 k
9/14/2016 18:00 9/15/2016 6:00 CAPE 2043.728 2209.68 1761.32 1989.58 2086.367 18 k
9/14/2016 18:00 9/15/2016 12:00 CAPE 2123.021 2258 1954.9 2085.106 2155.768 18 k
9/14/2016 18:00 9/15/2016 18:00 CAPE 2079.35 2397.08 1745.22 2011.772 2135.195 18 k
9/14/2016 18:00 9/14/2016 18:00 WSPD 10.30410353 11.91721456 8.248297085 9.838215725 10.75774552 18 k
9/14/2016 18:00 9/15/2016 0:00 WSPD 10.9400117 12.43605914 9.573964769 10.59848982 11.28932813 18 k
9/14/2016 18:00 9/15/2016 6:00 WSPD 11.46127399 12.81606087 10.4988286 11.2154979 11.73633011 18 k
9/14/2016 18:00 9/15/2016 12:00 WSPD 11.17043143 12.43677466 9.707966369 10.84331329 11.49746871 18 k
9/14/2016 18:00 9/15/2016 18:00 WSPD 9.871976672 11.04788095 8.228105178 9.523215227 10.15348249 18 k
Upvotes: 2
Views: 1027
Reputation: 1376
As per my research, it's not possible to generate a single plot the way you would like to. If you take a look at the plotly subplots documentation, you'll notice that subplots can only be populated with traces that are graph objects. The px.scatter()
figure you're generating for a single parameter is already made up of multiple traces. A subplot cannot be populated with figures, only traces.
First, I adjusted your code to produce subplots. Disregarding your dataframe manipulation and only focusing on the plotly syntax, there are some errors I found in this part:
for n in range(len(parameter)):
fig.append_trace(px.scatter(dff, x='forecast_time', y=dff.columns[5:10], row=n, col=1))
As mentioned, the trace needs to a graph object and not a figure.
The row count starts at 1, not 0.
row, col are parameters for append_trace, so they need to be moved outside their current bracket.
You'd need to filter dff for the right parameter in either case.
Here's my full code and data that produces subplots
import dash
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from dash import dcc, html
from dash.dependencies import Input, Output
df = pd.read_csv('values.csv')
df.astype({
'run_time': 'datetime64',
'forecast_time': 'datetime64',
'parameter': 'string',
'mean': 'float64',
'max': 'float64',
'min': 'float64',
'ci_low': 'float64',
'ci_high': 'float64',
'r_hour': 'int64',
'loc': 'string'
})
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Dropdown(
id="location",
options=[{'label': 'K', 'value': 'k'},
{'label': 'W', 'value': 'w'}],
value='w',
placeholder='Select a location',
),
dcc.Dropdown(
id="r_hour",
options=[{'label': '00Z', 'value': 0},
{'label': '06Z', 'value': 6},
{'label': '12Z', 'value': 12},
{'label': '18Z', 'value': 18}],
value='12',
placeholder="Select a forecast time",
),
dcc.Dropdown(
id="parameter",
options=[{"label": x, "value": x} for x in df["parameter"].unique()],
placeholder='Select a parameter',
value='CAPE',
multi=True
),
dcc.Graph(id="graph1", figure={}),
]
)
@app.callback(
Output("graph1", "figure"),
Input("location", "value"),
Input("r_hour", "value"),
Input('parameter', 'value'),
)
def update_graph1(loc, r_hour, parameter):
if loc is None or r_hour is None or parameter is None:
return dash.no_update
parameter = parameter if isinstance(parameter, list) else [parameter]
dff = df[(df['loc'] == loc) & (df['r_hour'] == int(r_hour)) & (df['parameter'].isin(parameter))]
if len(parameter) > 1:
fig = make_subplots(rows=len(parameter), cols=1)
r = 1
for p in parameter:
fig.append_trace(
go.Scatter(x=dff['forecast_time'], y=dff[dff['parameter'] == p]['mean']),
row=r, col=1
)
r += 1
return fig
return px.scatter(dff, x='forecast_time', y=['mean', 'max', 'min', 'ci_low', 'ci_high'])
if __name__ == '__main__':
app.run_server(debug=True)
run_time,forecast_time,parameter,mean,max,min,ci_low,ci_high,r_hour,loc
9/14/2016 12:00,9/14/2016 18:00,APCP,0.041483684,0.127401644,0.009763785,0.029901197,0.060754167,12,w
9/14/2016 12:00,9/15/2016 0:00,APCP,0.037159666,0.140004013,0.000519685,0.026262613,0.056544125,12,w
9/14/2016 12:00,9/15/2016 6:00,APCP,0.053111446,0.163689065,0.009968509,0.038685651,0.075773072,12,w
9/14/2016 12:00,9/15/2016 12:00,APCP,0.02625966,0.083563037,0.004811026,0.01951379,0.036598051,12,w
9/14/2016 12:00,9/15/2016 18:00,APCP,0.037727973,0.10328352,0.007964571,0.028584858,0.05144924,12,w
9/14/2016 12:00,9/14/2016 12:00,CAPE,2531.348,2783.08,2364.6,2484.948,2583.0745,12,w
9/14/2016 12:00,9/14/2016 18:00,CAPE,2343.2995,2618.87,1895.03,2240.252,2419.445,12,w
9/14/2016 12:00,9/15/2016 0:00,CAPE,2270.763,2521.38,1965.84,2203.535,2334.4885,12,w
9/14/2016 12:00,9/15/2016 6:00,CAPE,2422.276,2637.64,2000.03,2340.4395,2476.8495,12,w
9/14/2016 12:00,9/15/2016 12:00,CAPE,2560.587,2765.51,2167.7,2484.0775,2621.121,12,w
9/14/2016 12:00,9/15/2016 18:00,CAPE,2434.641,2643.32,2177.51,2375.872,2485.731,12,w
9/14/2016 12:00,9/14/2016 12:00,WSPD,13.67982033,14.92190326,11.93637952,13.28460204,14.01356071,12,w
9/14/2016 12:00,9/14/2016 18:00,WSPD,13.00873562,14.51315919,11.61153561,12.670458,13.35743091,12,w
9/14/2016 12:00,9/15/2016 0:00,WSPD,13.15495082,14.50841618,11.95527281,12.86944934,13.47149018,12,w
9/14/2016 12:00,9/15/2016 6:00,WSPD,12.25102442,13.75337432,10.89424146,11.92889921,12.55852141,12,w
9/14/2016 12:00,9/15/2016 12:00,WSPD,13.61138813,14.97033537,11.80458902,13.27546662,13.8712801,12,w
9/14/2016 12:00,9/15/2016 18:00,WSPD,11.86885821,13.08368289,10.74028982,11.607135,12.14320021,12,w
9/14/2016 18:00,9/15/2016 0:00,APCP,0.034182499,0.079354374,0.003188978,0.025235644,0.044085457,18,w
9/14/2016 18:00,9/15/2016 6:00,APCP,0.046251403,0.144504015,0.006216539,0.034403562,0.064499641,18,w
9/14/2016 18:00,9/15/2016 12:00,APCP,0.029244504,0.23320485,0.005094491,0.016554536,0.07372189,18,w
9/14/2016 18:00,9/15/2016 18:00,APCP,0.024053163,0.087622095,0.002917324,0.016503159,0.03626065,18,w
9/14/2016 18:00,9/14/2016 18:00,CAPE,2435.6345,2712.71,2094.12,2370.4595,2499.1125,18,w
9/14/2016 18:00,9/15/2016 0:00,CAPE,2276.4495,2400.68,2040.39,2231.341,2310.1765,18,w
9/14/2016 18:00,9/15/2016 6:00,CAPE,2443.665,2747.34,2135.22,2382.9555,2505.553,18,w
9/14/2016 18:00,9/15/2016 12:00,CAPE,2499.848,2758.34,2242.96,2442.4635,2557.9475,18,w
9/14/2016 18:00,9/15/2016 18:00,CAPE,2445.8005,2623,2252.07,2392.139,2496.5585,18,w
9/14/2016 18:00,9/14/2016 18:00,WSPD,12.80103404,14.36857011,11.76708975,12.54172344,13.11939702,18,w
9/14/2016 18:00,9/15/2016 0:00,WSPD,13.2089427,15.63134179,11.92824288,12.92959876,13.63760661,18,w
9/14/2016 18:00,9/15/2016 6:00,WSPD,12.72761899,13.52581477,11.74122287,12.46831392,12.95820863,18,w
9/14/2016 18:00,9/15/2016 12:00,WSPD,13.78891527,14.57733477,12.43695412,13.5125545,13.98578588,18,w
9/14/2016 18:00,9/15/2016 18:00,WSPD,11.80539318,12.4321654,10.59583493,11.54830383,11.9986291,18,w
9/14/2016 12:00,9/14/2016 18:00,APCP,0.024927179,0.057874047,0.011023628,0.020621271,0.032037025,12,k
9/14/2016 12:00,9/15/2016 0:00,APCP,0.012142526,0.072992165,0,0.006259058,0.024529935,12,k
9/14/2016 12:00,9/15/2016 6:00,APCP,0.0341449,0.0889843,0.003606301,0.02528151,0.045535458,12,k
9/14/2016 12:00,9/15/2016 12:00,APCP,0.013788196,0.058086646,0.000535433,0.008549217,0.022687808,12,k
9/14/2016 12:00,9/15/2016 18:00,APCP,0.007568902,0.024826785,0.001023623,0.005498428,0.011116148,12,k
9/14/2016 12:00,9/14/2016 12:00,CAPE,1915.985,2022.58,1724.18,1877.471,1944.124,12,k
9/14/2016 12:00,9/14/2016 18:00,CAPE,1765.312,1976.54,1571.52,1723.748,1808.896,12,k
9/14/2016 12:00,9/15/2016 0:00,CAPE,1903.907,2111.48,1630.76,1849.207,1955.516,12,k
9/14/2016 12:00,9/15/2016 6:00,CAPE,2022.187,2218.66,1744.28,1971.346,2066.359,12,k
9/14/2016 12:00,9/15/2016 12:00,CAPE,2117.713,2289.48,1977.74,2080.877,2160.069,12,k
9/14/2016 12:00,9/15/2016 18:00,CAPE,2035.243,2287.06,1737.66,1966.873,2093.823,12,k
9/14/2016 12:00,9/14/2016 12:00,WSPD,11.51403081,12.90299913,9.348005138,11.02996656,11.91310878,12,k
9/14/2016 12:00,9/14/2016 18:00,WSPD,10.66348483,12.10730058,8.536612865,10.2005094,11.04692859,12,k
9/14/2016 12:00,9/15/2016 0:00,WSPD,10.81256637,12.22364593,9.74415303,10.53260001,11.1350116,12,k
9/14/2016 12:00,9/15/2016 6:00,WSPD,11.10226976,12.35115476,9.882793516,10.80288164,11.39107227,12,k
9/14/2016 12:00,9/15/2016 12:00,WSPD,11.26334728,12.6892719,9.999631254,10.97207787,11.57319938,12,k
9/14/2016 12:00,9/15/2016 18:00,WSPD,9.835853253,11.13364239,7.475216637,9.385502624,10.13933703,12,k
9/14/2016 18:00,9/15/2016 0:00,APCP,0.017726388,0.074779568,0.002259844,0.011548038,0.028326,18,k
9/14/2016 18:00,9/15/2016 6:00,APCP,0.027098834,0.054606329,0.001393702,0.020021664,0.0343012,18,k
9/14/2016 18:00,9/15/2016 12:00,APCP,0.020631507,0.119322899,0.002086615,0.010669297,0.0426827,18,k
9/14/2016 18:00,9/15/2016 18:00,APCP,0.005209452,0.012196857,0,0.003969687,0.006824413,18,k
9/14/2016 18:00,9/14/2016 18:00,CAPE,1764.579,1914.96,1525.46,1722.144,1800.189,18,k
9/14/2016 18:00,9/15/2016 0:00,CAPE,1904.978,2052.38,1701.34,1861.194,1941.033,18,k
9/14/2016 18:00,9/15/2016 6:00,CAPE,2043.728,2209.68,1761.32,1989.58,2086.367,18,k
9/14/2016 18:00,9/15/2016 12:00,CAPE,2123.021,2258,1954.9,2085.106,2155.768,18,k
9/14/2016 18:00,9/15/2016 18:00,CAPE,2079.35,2397.08,1745.22,2011.772,2135.195,18,k
9/14/2016 18:00,9/14/2016 18:00,WSPD,10.30410353,11.91721456,8.248297085,9.838215725,10.75774552,18,k
9/14/2016 18:00,9/15/2016 0:00,WSPD,10.9400117,12.43605914,9.573964769,10.59848982,11.28932813,18,k
9/14/2016 18:00,9/15/2016 6:00,WSPD,11.46127399,12.81606087,10.4988286,11.2154979,11.73633011,18,k
9/14/2016 18:00,9/15/2016 12:00,WSPD,11.17043143,12.43677466,9.707966369,10.84331329,11.49746871,18,k
9/14/2016 18:00,9/15/2016 18:00,WSPD,9.871976672,11.04788095,8.228105178,9.523215227,10.15348249,18,k
Since your plan isn't feasible, what are your alternatives? You could produce multiple graphs. Thankfully, plotly allows for dynamic callbacks:
import dash
import pandas as pd
import plotly.express as px
from dash import dcc, html
from dash.dependencies import Input, Output
df = pd.read_csv('values.csv')
df.astype({
'run_time': 'datetime64',
'forecast_time': 'datetime64',
'parameter': 'string',
'mean': 'float64',
'max': 'float64',
'min': 'float64',
'ci_low': 'float64',
'ci_high': 'float64',
'r_hour': 'int64',
'loc': 'string'
})
PS = list(df["parameter"].unique())
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Dropdown(
id="location",
options=[{'label': 'K', 'value': 'k'},
{'label': 'W', 'value': 'w'}],
value='w',
placeholder='Select a location',
),
dcc.Dropdown(
id="r_hour",
options=[{'label': '00Z', 'value': 0},
{'label': '06Z', 'value': 6},
{'label': '12Z', 'value': 12},
{'label': '18Z', 'value': 18}],
value='12',
placeholder="Select a forecast time",
),
dcc.Dropdown(
id="parameter",
options=[{"label": p, "value": p} for p in PS],
placeholder='Select a parameter',
value='CAPE',
multi=True
),
*[dcc.Graph(id=p, figure={}, style={'display': 'none'}) for p in PS]
]
)
@app.callback(
[Output(p, 'figure') for p in PS],
[Output(p, 'style') for p in PS],
Input("location", "value"),
Input("r_hour", "value"),
Input('parameter', 'value')
)
def update_graph1(loc, r_hour, parameter):
if loc is None or r_hour is None or parameter is None:
return dash.no_update
parameter = parameter if isinstance(parameter, list) else [parameter]
dff = df[(df['loc'] == loc) & (df['r_hour'] == int(r_hour)) & (df['parameter'].isin(parameter))]
figures = [{} for _ in range(len(PS))]
styles = [{'display': 'none'} for _ in range(len(PS))]
for p in parameter:
pi = PS.index(p)
figures[pi] = px.scatter(
dff[dff['parameter'] == p],
x='forecast_time', y=['mean', 'max', 'min', 'ci_low', 'ci_high']
)
styles[pi]['display'] = 'block'
return *figures, *styles
if __name__ == '__main__':
app.run_server(debug=True)
Here's the result:
Explanation
I create a dcc.Graph for every unique parameter and set its display style to none
on default. I use the parameter as an ID to determine the index of the graph in the list of unique paramters, but you could just aswell create a mapping for that.
Then, I create a callback for each Graph figure and for each Graph style with the list comprehensions you can see. In the function, I filter the data, create default figures (empty) and styles (hidden), and for each user-selected parameter, I create a real figure and set its display style to block
, which turns it visible.
The *
operator I use in various places is to unpack a collection. E.g. [1, 2, 3, *[4, 5]] -> [1, 2, 3, 4, 5]
Upvotes: 2