Dash Python - 选择多个参数时制作子图

Dash Python - Making subplots when multiple parameters are selected

我正在尝试制作一个交互式绘图,用户可以在其中 select 一个位置,然后是一个时间,然后是参数列表中的一个。我能够绘制每个参数的基本图,但我想做的是,当列表中的多个参数被 selected 时,每个参数开始形成一个堆叠的子图。我有一个我认为是正确的循环,但它似乎没有 运行 通过它来制作子图。

寻求有关如何在多个参数的条件下添加子图的帮助selected。

代码如下:

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)

数据示例:

    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

根据我的研究,不可能以您想要的方式生成 单个 绘图。如果您查看 plotly subplots documentation,您会注意到子图只能填充 traces,即 graph objects。您为单个参数生成的 px.scatter() 已经由多个轨迹组成。子图不能填充图形,只能填充痕迹。

首先,我调整了您的代码以生成子图。忽略你的数据框操作,只关注 plotly 语法,我在这部分发现了一些错误:

for n in range(len(parameter)):
    fig.append_trace(px.scatter(dff, x='forecast_time', y=dff.columns[5:10], row=n, col=1))
  1. 如前所述,跟踪需要图形对象而不是图形。

  2. 行数从 1 开始,而不是 0。

  3. row, col 是 append_trace 的参数,因此需要将它们移出当前括号。

  4. 在任何一种情况下,您都需要为正确的参数过滤 dff。

这是我生成子图的完整代码和数据

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

既然你的计划不可行,你有什么选择?您可以生成多个图表。值得庆幸的是,plotly 允许动态回调:

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)

结果如下:

说明

我为每个唯一参数创建一个dcc.Graph,并将其显示样式默认设置为none。我使用参数作为 ID 来确定图形在唯一参数列表中的索引,但您也可以为此创建一个映射。

然后,我使用您可以看到的列表理解为每个图表图形和每个图表样式创建一个回调。在函数中,我过滤数据,创建默认图形(空)和样式(隐藏),并为每个 user-selected 参数创建一个真实图形并设置其显示样式设置为 block,使其可见。

我在各个地方使用的*运算符是解压一个集合。例如。 [1, 2, 3, *[4, 5]] -> [1, 2, 3, 4, 5]