【问题标题】:Plotly Dash: How to change image on button clickPlotly Dash:如何在按钮单击时更改图像
【发布时间】:2021-11-13 19:45:35
【问题描述】:

当我试图使用该示例来完成我的用例时,我在以下线程的答案部分中不知不觉地添加了:

Plotly: How to display graph after clicking a button?

我正在寻找一个非常相似的解决方案,我尝试了建议 2(来自上述线程),因为我想根据用户选择的单击按钮来显示图像。我在一个目录下有image_1image_2image_3image_4。到目前为止,我已经尝试过如下:

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

pd.options.plotting.backend = "plotly"
from datetime import datetime

palette = px.colors.qualitative.Plotly

# sample data
df = pd.DataFrame({'Prices': [1, 10, 7, 5, np.nan, np.nan, np.nan],
                   'Predicted_prices': [np.nan, np.nan, np.nan, 5, 8, 6, 9]})

# app setup
app = dash.Dash()

# controls
controls = dcc.Card(
    [dcc.FormGroup(
        [
            dcc.Label("Options"),
            dcc.RadioItems(id="display_figure",
                           options=[{'label': 'None', 'value': 'Nope'},
                                    {'label': 'Figure 1', 'value': 'Figure1'},
                                    {'label': 'Figure 2', 'value': 'Figure2'},
                                    {'label': 'Figure 3', 'value': 'Figure3'}
                                    ],
                           value='Nope',
                           labelStyle={'display': 'inline-block', 'width': '10em', 'line-height': '0.5em'}
                           )
        ],
    ),
        dcc.FormGroup(
            [dcc.Label(""), ]
        ),
    ],
    body=True,
    style={'font-size': 'large'})

app.layout = dcc.Container(
    [
        html.H1("Button for predictions"),
        html.Hr(),
        dcc.Row([
            dcc.Col([controls], xs=4),
            dcc.Col([
                dcc.Row([
                    dcc.Col(dcc.Graph(id="predictions")),
                ])
            ]),
        ]),
        html.Br(),
        dcc.Row([

        ]),
    ],
    fluid=True,
)


@app.callback(
    Output("predictions", "figure"),
    [Input("display_figure", "value"),

     ],
)
def make_graph(display_figure):
    # main trace
    y = 'Prices'
    y2 = 'Predicted_prices'
    #     print(display_figure)
    if 'Nope' in display_figure:
        fig = go.Figure()
        fig.update_layout(plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)',
                          yaxis=dict(showgrid=False, zeroline=False, tickfont=dict(color='rgba(0,0,0,0)')),
                          xaxis=dict(showgrid=False, zeroline=False, tickfont=dict(color='rgba(0,0,0,0)')))
        return fig

    if 'Figure1' in display_figure:
        fig = go.Figure(go.Scatter(name=y, x=df.index, y=df[y], mode='lines'))
        fig.add_traces(go.Scatter(name=y, x=df.index, y=df[y2], mode='lines'))
        fig.update_layout(template='plotly_dark')

    # prediction trace
    if 'Figure2' in display_figure:
        fig = go.Figure((go.Scatter(name=y, x=df.index, y=df[y], mode='lines')))
        fig.add_traces(go.Scatter(name=y, x=df.index, y=df[y2], mode='lines'))
        fig.update_layout(template='seaborn')

    if 'Figure3' in display_figure:
        fig = go.Figure((go.Scatter(name=y, x=df.index, y=df[y], mode='lines')))
        fig.add_traces(go.Scatter(name=y, x=df.index, y=df[y2], mode='lines'))
        fig.update_layout(template='plotly_white')

    # Aesthetics
    fig.update_layout(margin={'t': 30, 'b': 0, 'r': 0, 'l': 0, 'pad': 0})
    fig.update_layout(hovermode='x')
    fig.update_layout(showlegend=True, legend=dict(x=1, y=0.85))
    fig.update_layout(uirevision='constant')
    fig.update_layout(title="Prices and predictions")

    return (fig)


app.run_server(debug=True)

但我收到以下错误,无法继续进行。

line 24, in <module>
    controls = dcc.Card(
AttributeError: module 'dash_core_components' has no attribute 'Card'

【问题讨论】:

    标签: python plotly-dash plotly-python


    【解决方案1】:

    问题在于您的代码中使用的不同组件是在不同的库中定义的(dash_core_componentsdash_html_componentsdash_bootstrap_components),而您正试图从同一个库 (dash_core_components) 中获取所有组件。例如,dcc.Card 应替换为dbc.Card,其中dbc 代表dash_bootstrap_components,请参见下面的代码。

    import pandas as pd
    import numpy as np
    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    import dash_bootstrap_components as dbc
    from dash.dependencies import Input, Output
    import plotly.graph_objs as go
    
    # sample data
    df = pd.DataFrame({
        'Prices': [1, 10, 7, 5, np.nan, np.nan, np.nan],
        'Predicted_prices': [np.nan, np.nan, np.nan, 5, 8, 6, 9]
    })
    
    # app setup
    app = dash.Dash()
    
    # controls
    controls = dbc.Card([
    
            dbc.FormGroup([
    
                html.Label('Options'),
    
                dcc.RadioItems(
                    id='display_figure',
                    options=[
                        {'label': 'None', 'value': 'None'},
                        {'label': 'Figure 1', 'value': 'Figure1'},
                        {'label': 'Figure 2', 'value': 'Figure2'},
                        {'label': 'Figure 3', 'value': 'Figure3'}
                    ],
                    value='None',
                    labelStyle={
                        'display': 'inline-block',
                        'width': '10em',
                        'line-height': '0.5em'
                    }
                )
    
            ]),
    
        ],
    
        body=True,
        style={'font-size': 'large'}
    
    )
    
    app.layout = dbc.Container([
    
            html.H1('Button for predictions'),
    
            html.Hr(),
    
            dbc.Row([
    
                dbc.Col([controls], xs=4),
    
                dbc.Col([
                    dbc.Row([
                        dbc.Col(dcc.Graph(id='predictions')),
                    ])
    
                ]),
            ]),
    
        ],
    
        fluid=True,
    
    )
    
    
    @app.callback(
        Output('predictions', 'figure'),
        [Input('display_figure', 'value')],
    )
    def make_graph(display_figure):
    
        y = 'Prices'
        y2 = 'Predicted_prices'
    
        if 'Figure1' in display_figure:
            fig = go.Figure(go.Scatter(name=y, x=df.index, y=df[y], mode='lines'))
            fig.add_trace(go.Scatter(name=y, x=df.index, y=df[y2], mode='lines'))
            fig.update_layout(template='plotly_dark')
            fig.update_layout(title='Prices and predictions')
    
        elif 'Figure2' in display_figure:
            fig = go.Figure((go.Scatter(name=y, x=df.index, y=df[y], mode='lines')))
            fig.add_trace(go.Scatter(name=y, x=df.index, y=df[y2], mode='lines'))
            fig.update_layout(template='seaborn')
            fig.update_layout(title='Prices and predictions')
    
        elif 'Figure3' in display_figure:
            fig = go.Figure((go.Scatter(name=y, x=df.index, y=df[y], mode='lines')))
            fig.add_trace(go.Scatter(name=y, x=df.index, y=df[y2], mode='lines'))
            fig.update_layout(template='plotly_white')
            fig.update_layout(title='Prices and predictions')
    
        else:
            fig = go.Figure()
            fig.update_layout(
                plot_bgcolor='rgba(0,0,0,0)',
                paper_bgcolor='rgba(0,0,0,0)',
                yaxis=dict(showgrid=False, zeroline=False, tickfont=dict(color='rgba(0,0,0,0)')),
                xaxis=dict(showgrid=False, zeroline=False, tickfont=dict(color='rgba(0,0,0,0)'))
            )
    
        fig.update_layout(margin={'t': 30, 'b': 0, 'r': 0, 'l': 0, 'pad': 0})
        fig.update_layout(hovermode='x')
        fig.update_layout(showlegend=True, legend=dict(x=1, y=0.85))
        fig.update_layout(uirevision='constant')
    
        return fig
    
    if __name__ == '__main__':
        app.run_server(host='127.0.0.1', debug=True)
    

    解决此问题后,您可以更新应用程序以显示静态 PNG 文件,而不是如下所示的交互式图表。请注意,dcc.Graph 组件已被 html.Img 组件替换,figure 属性已被 src 属性替换。

    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    import dash_bootstrap_components as dbc
    from dash.dependencies import Input, Output
    
    # app setup
    app = dash.Dash()
    
    # controls
    controls = dbc.Card([
    
            dbc.FormGroup([
    
                html.Label('Options'),
    
                dcc.RadioItems(
                    id='display_figure',
                    options=[
                        {'label': 'None', 'value': 'None'},
                        {'label': 'Figure 1', 'value': 'Figure1'},
                        {'label': 'Figure 2', 'value': 'Figure2'},
                        {'label': 'Figure 3', 'value': 'Figure3'}
                    ],
                    value='None',
                    labelStyle={
                        'display': 'inline-block',
                        'width': '10em',
                        'line-height': '0.5em'
                    }
                )
    
            ]),
    
        ],
    
        body=True,
        style={'font-size': 'large'}
    
    )
    
    app.layout = dbc.Container([
    
            html.H1('Button for predictions'),
    
            html.Hr(),
    
            dbc.Row([
    
                dbc.Col([controls], xs=4),
    
                dbc.Col([
                    dbc.Row([
                        dbc.Col(html.Img(id='predictions')),
                    ])
    
                ]),
            ]),
    
        ],
    
        fluid=True,
    
    )
    
    @app.callback(
        Output('predictions', 'src'),
        [Input('display_figure', 'value')],
    )
    def make_graph(display_figure):
    
        if 'Figure1' in display_figure:
            return app.get_asset_url('image_1.png')
    
        elif 'Figure2' in display_figure:
            return app.get_asset_url('image_2.png')
    
        elif 'Figure3' in display_figure:
            return app.get_asset_url('image_3.png')
    
        else:
            return None
    
    if __name__ == '__main__':
        app.run_server(host='127.0.0.1', debug=True)
    

    另请注意,PNG 文件需要保存在assets 文件夹中,如下所示:

    【讨论】:

    • 非常感谢您的时间和帮助。上述解决方案有效。我的用例是我已经生成了 3 个 png 文件,分别为 image_1、image_2 和 image_3。单击按钮时如何渲染这些静态图像。上面的示例生成散点图,但在我的情况下,我想显示这些静态图像。请让我知道一个例子。再次感谢。
    • 是的。它可以工作,我可以渲染静态图像,我相信这个例子对很多人都有用。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 2014-06-15
    相关资源
    最近更新 更多