plotly dash 的模式匹配回调 - python

问题描述 投票:0回答:1

我有一个下拉菜单,可以让我过滤分类图。单独的回调允许用户将该图从条形图更改为饼图。这部分按预期工作。

我有单独的滑块组件,可以调整条形图或饼图的设置。问题是滑块固定到位。 是否可以根据单选项目中的选择添加/删除相关滑块?

如果选择条形图(见下文),则只有两个条形滑块应该可见。另外两个应该被丢弃或移除。相反,如果选择了馅饼,就会发生相反的情况。条形滑块被移除以代替饼图滑块。

过滤 div 上的布局应保持不变。

import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd

df = pd.DataFrame({
   'Fruit': ['Apple','Banana','Orange','Kiwi','Lemon'],
   'Value': [1,2,4,8,6],
   })

external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]

app = dash.Dash(__name__, external_stylesheets = external_stylesheets)

filter_box = html.Div(children=[

    html.Div(children=[

        html.Label('Fruit', style = {}),
        dcc.Dropdown(
            id = 'value_type',
            options = [
                {'label': x, 'value': x} for x in df['Fruit'].unique()
            ],
            value = df['Fruit'].unique(),
            multi = True,
            clearable = True
        ),

        html.Label('Cat Chart', style = {'display': 'inline','paddingTop': '0rem', "justifyContent": "center"}),
        dcc.RadioItems(['Bar','Pie'],'Bar', 
                       id = 'catmap', 
                       ),

       html.Label('Bar Transp', style = {'display': 'inline-block', 'paddingTop': '0.1rem',}),
        dcc.Slider(0, 1, 0.2,
               value = 0.6,
               id = 'bar_transp'),

        html.Label('Bar Width', style = {'display': 'inline-block'}),
        dcc.Slider(200, 1000, 200,
               value = 600,
               id = 'bar_width'),

        html.Label('Pie Transp', style = {'display': 'inline-block', 'paddingTop': '0.1rem',}),
        dcc.Slider(0, 1, 0.2,
               value = 0.6,
               id = 'pie_transp'),

        html.Label('Pie Hole', style = {'display': 'inline-block'}),
        dcc.Slider(0, 1, 0.2,
               value = 0.4,
               id = 'pie_hole'),

    ], className = "vstack",            
    )
])

app.layout = dbc.Container([
    dbc.Row([
        dbc.Col([
            dbc.Row([
                dbc.Col(html.Div(filter_box), 
                        ),
            ]),
        ]),
        dbc.Col([
            dbc.Row([
                dcc.Graph(id = 'type-chart'),
            ]),
        ])
    ])
], fluid = True)

@app.callback(
    Output('type-chart', 'figure'),
    [Input('value_type', 'value'), 
     Input('catmap', 'value'), 
     Input('bar_transp', 'value'), 
     Input('bar_width', 'value'), 
     Input('pie_transp', 'value'), 
     Input('pie_hole', 'value'), 
    ])     

def chart(value_type, catmap, bar_transp, bar_width, pie_transp, pie_hole):

    dff = df[df['Fruit'].isin(value_type)]

    if catmap == 'Bar':

        df_count = dff.groupby(['Fruit'])['Value'].count().reset_index(name = 'counts')

        if df_count.empty == True:
            type_fig = go.Figure()

        else:
            df_count = df_count

            type_fig = px.bar(x = df_count['Fruit'], 
                      y = df_count['counts'],
                      color = df_count['Fruit'],
                      opacity = bar_transp,
                      width = bar_width
                      )

    elif catmap == 'Pie':

        df_count = dff.groupby(['Fruit'])['Value'].count().reset_index(name = 'counts')

        if df_count.empty == True:
            type_fig = go.Figure()

        else:
            df_count = df_count

            type_fig = px.pie(df_count,
                              values = df_count['counts'],
                              opacity = pie_transp,
                              hole = pie_hole
                             )

    return type_fig

if __name__ == '__main__':
    app.run_server(debug = True)

enter image description here

javascript python callback plotly pattern-matching
1个回答
0
投票

在这种情况下不需要模式匹配回调,但如果要动态创建过滤器则可能需要。相反,为了根据所选图形类型添加/删除相关滑块,您可以将它们包装在组件中(如

children
)并使用回调来更新该组件的
children
属性。

但是,我建议您只显示/隐藏滑块,而不是添加/删除它们,以便在图形类型更新中保留它们的状态:

  • 为每种类型使用一个包装组件(此处为“filter_bar”和“filter_pie”):

    filter_box = html.Div(children=[
    
        html.Div(children=[
    
            html.Label('Fruit', style = {}),
            dcc.Dropdown(
                id = 'value_type',
                options = [
                    {'label': x, 'value': x} for x in df['Fruit'].unique()
                ],
                value = df['Fruit'].unique(),
                multi = True,
                clearable = True
            ),
    
            html.Label('Cat Chart', style = {'display': 'inline','paddingTop': '0rem', "justifyContent": "center"}),
            dcc.RadioItems(['Bar','Pie'],'Bar',
                        id = 'catmap',
                        ),
    
            html.Div(id='filter_bar', children=[
                html.Label('Bar Transp', style = {'display': 'inline-block', 'paddingTop': '0.1rem',}),
                dcc.Slider(0, 1, 0.2,
                    value = 0.6,
                    id = 'bar_transp'),
    
                html.Label('Bar Width', style = {'display': 'inline-block'}),
                dcc.Slider(200, 1000, 200,
                    value = 600,
                    id = 'bar_width'),
            ]),
    
    
            html.Div(id='filter_pie', children=[
                html.Label('Pie Transp', style = {'display': 'inline-block', 'paddingTop': '0.1rem',}),
                dcc.Slider(0, 1, 0.2,
                    value = 0.6,
                    id = 'pie_transp'),
    
                html.Label('Pie Hole', style = {'display': 'inline-block'}),
                dcc.Slider(0, 1, 0.2,
                    value = 0.4,
                    id = 'pie_hole'),
            ])
    
        ], className = "vstack",
        )
    ])
    
  • 并在回调中更新其

    style
    属性:

     @app.callback(
        Output('filter_bar', 'style'),
        Output('filter_pie', 'style'),
        Input('catmap', 'value')
    )
    def display_sliders(catmap):
        if catmap == 'Bar':
            return {}, {'display': 'none'}
    
        if catmap == 'Pie':
            return {'display': 'none'}, {}
    
        return {'display': 'none'}, {'display': 'none'}
    
© www.soinside.com 2019 - 2024. All rights reserved.