Plotly:如何为具有完全不同数据和布局的图形制作一个 plotly 下拉菜单?

Plotly: How to make a plotly dropdown menu for figures with wholly different data and layouts?

我正在尝试制作一个带有下拉菜单的交互式绘图,该菜单从一系列完全不相关的图形中进行选择(即依赖于不同数据结构且布局非常不同的绘图)。我见过的所有下拉菜单示例都基于一组数据或多个数据集,但使用相对简单的绘图布局。这不适用于我试图合并数十个具有非常不同的布局和基础数据的图的情况。下面是我试图合并的图的一个工作示例。每个地块的布局都非常不同:

import plotly.graph_objs as go
import plotly.express as px
import pandas as pd

# Prep some fake data for a bar graph
df1 = pd.DataFrame(dict(
    bar_y = ['Bar1', 'Bar2'],
    bar_x = [2,3],
    bar_z = [1,2]
))

# Make bar graph
fig1 = px.bar(df1, 
              x="bar_x", 
              y='bar_y',
              color='bar_z',
              orientation='h',
)    

# Add layout attributes
fig1.update_layout(
    xaxis_title="<b> Bar graph title <b>",
    yaxis_title="<b> Bar x axis <b>",
    legend_title="<b> Bar y axis <b>",        
    xaxis = dict(
        showgrid=True,
        ticks="",
        showline = False,
        gridcolor = 'white'
    )
)       

# Prep some fake data for a line graph
df2 = pd.DataFrame(dict(
    line_y = [3,2,1, 1,2,3],
    line_x = [1,2,3,1,2,3],
    line_group = ['line1','line1','line1','line2','line2','line2']
))

# Make an ugly line graph
fig2 = px.line(
    df2,
    x= 'line_x',
    y= 'line_y',
    color = 'line_group'
)

# Add a number of layout attributes that are distinct from those above
fig2.update_layout(
    shapes=[dict(
      type= 'line',
      fillcolor = 'black',
      line_width=2,
      yref= 'y', y0= 0, y1= 0,
      xref= 'x', x0= 1, x1= 3,
    )],
    xaxis_title="<b> Line graph title <b>",
    yaxis_title="<b> Line x axis <b>",
    legend_title="<b> Line y axis <b>",
    template='simple_white',
    hoverlabel=dict(bgcolor="white")
)


# Create a dropdown menu. Below is close to what I'd like to do, but the data statements are not working correctly and the shape in fig2 is causing problems...
fig3 = go.Figure()
fig3.update_layout(
    updatemenus=[
        dict(
            active=0,
            buttons=list([
                dict(label="Bar Graph",
                     method="update",
                     args=[fig1.to_dict()['data'],
                           fig1.to_dict()['layout']]
                    ),
                dict(label="Line Graph",
                     method="update",
                     args=[fig2.to_dict()['data'],
                           fig2.to_dict()['layout']]
                    ),
        ]))
    ]                           
)

看来我几乎能够根据每个原始图形的布局正确更新每个下拉组成图的布局。但是,是否可以通过这种方法更新数据 还有吗?

我可能在这里完全漏掉了要点。在这种情况下,释放 Dash 应用程序也可能有点矫枉过正。但我想向您展示以下设置如何使您能够使用 dcc.Dropdown() return 完全不同的图形对象。下面的代码片段将生成以下应用程序:

如果你现在 select fig2,你会得到这个:

如果这是您可以使用的东西,我们可以讨论更多细节。此外,带有非常宽的下拉按钮的设计诚然不是最漂亮的设计,但我认为设计不是这里的主要设计 objective。

完整代码:

import dash
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 numpy as np
from plotly.subplots import make_subplots
import plotly.express as px

# Prep some fake data for a bar graph
df1 = pd.DataFrame(dict(
    bar_y = ['Bar1', 'Bar2'],
    bar_x = [2,3],
    bar_z = [1,2]
))

# Make bar graph
fig1 = px.bar(df1, 
              x="bar_x", 
              y='bar_y',
              color='bar_z',
              orientation='h',
)    

# Add layout attributes
fig1.update_layout(
    xaxis_title="<b> Bar graph title <b>",
    yaxis_title="<b> Bar x axis <b>",
    legend_title="<b> Bar y axis <b>",        
    xaxis = dict(
        showgrid=True,
        ticks="",
        showline = False,
        gridcolor = 'white'
    )
)       

# Prep some fake data for a line graph
df2 = pd.DataFrame(dict(
    line_y = [3,2,1, 1,2,3],
    line_x = [1,2,3,1,2,3],
    line_group = ['line1','line1','line1','line2','line2','line2']
))

# Make an ugly line graph
fig2 = px.line(
    df2,
    x= 'line_x',
    y= 'line_y',
    color = 'line_group'
)

# Add a number of layout attributes that are distinct from those above
fig2.update_layout(
    shapes=[dict(
      type= 'line',
      fillcolor = 'black',
      line_width=2,
      yref= 'y', y0= 0, y1= 0,
      xref= 'x', x0= 1, x1= 3,
    )],
    xaxis_title="<b> Line graph title <b>",
    yaxis_title="<b> Line x axis <b>",
    legend_title="<b> Line y axis <b>",
    template='simple_white',
    hoverlabel=dict(bgcolor="white")
)

# app = JupyterDash(__name__)
app = dash.Dash()
figs = ['fig1', 'fig2']

app.layout = html.Div([
    html.Div([
        dcc.Graph(id='plot'),

        html.Div([
            dcc.Dropdown(
                id='variables',
                options=[{'label': i, 'value': i} for i in figs],
                value=figs[0]
            )
        ])
    ])
])

@app.callback(
    Output('plot', 'figure'),
    [Input('variables', 'value')])

def update_graph(fig_name):

    if fig_name == 'fig1':
#         fig=go.Figure(go.Scatter(x=[1,2,3], y = [3,2,1]))
        return fig1


    if fig_name == 'fig2':
#         fig=go.Figure(go.Bar(x=[1,2,3], y = [3,2,1]))
        return fig2
        
# app.run_server(mode='external', debug=True)
app.run_server(debug=True,
           use_reloader=False # Turn off reloader if inside Jupyter
          )