mckinsey / vizro

Vizro is a toolkit for creating modular data visualization applications.
https://vizro.readthedocs.io/en/stable/
Apache License 2.0
2.49k stars 112 forks source link

the selector option is from another selector #180

Open bvbvtw opened 8 months ago

bvbvtw commented 8 months ago

Question

I'd like to dynamic change the selector options according to the another selector. for example: I use titanic_data to set dropdown list: first dropdown is pclass , it's including 1,2,3 second dropdown is deck it's including A,B,C,D,E,F,G What I want is when select plass=2 on the first dropdown, the second dropdown only show D,E,F because there are only deck D,E,F on pclass=2 This function can be done by callback in dash/plotly. How can I achieve this function inVizro? Please advise, thank you! image

Code/Examples

No response

Other information

No response

vizro version

No response

Python version

No response

OS

No response

Code of Conduct

Joseph-Perkins commented 8 months ago

Thank you for the clear explanation @bvbvtw ! That makes sense, and it seems that it would be similar to what might often be described as ‘cascading’ or ‘hierarchical’ filtering

This functionality is currently not available in Vizro 0.1.6 yet, however it may soon be possible to achieve through future functionality related to customising callbacks, which is currently in development

When the underlying functionality to apply custom callbacks is released shortly, we will reply here whether it is possible to use that to achieve the same outcome of cascading filters (or else will give an indication about when that functionality might be available as part of the core functionality instead)

bvbvtw commented 8 months ago

@Joseph-Perkins Thanks your prompt reply,

I've learn that it is possible to create custom components from documentation. The following code demonstrates how I use Dash/Plotly to achieve cascading filters. But I am not sure if I can use the callback method as following code to customize the controller in order to achieve cascading filters functionality. Please advice, thank you very much!

####################################### from dash import Dash, dcc, html, Input, Output, State, dash_table, callback import dash app = dash.Dash()

category_lst = [category[0] for category in category_table] tabs = html.Div( [html.P(), dcc.Dropdown(id='in_category', options = category_lst, placeholder="Select a category" ),

 dcc.Dropdown(id='in_item', 
              #options = ppid_lst, 
              placeholder="Select a item"
              ), 

])

@app.callback(Output("in_item", component_property='options'), Input(component_id='in_category', component_property='value'), prevent_initial_call=True ) def platform_ppid_selected(the_category): sql = f""" SELECT distinct item FROM table where item = '{the_category}' """ item_lst = [item[0] for item in pd.read_sql(sql, engine)] return item_lst #########################

petar-qb commented 8 months ago

Hi @bvbvtw. It's possible to use Vizro in combination with the Dash which makes a requested feature possible.

Here's an example with the plotly.express.data.gapminder() data where the "country filter" options are filtered by "continent filter" selected value:

import dash
import pandas as pd
import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.tables import dash_data_table

def create_country_analysis():
    df_gapminder = px.data.gapminder()

    @dash.callback(
        dash.Output("country_selector_id", "options"),
        dash.Output("country_selector_id", "value"),
        dash.Input("continent_selector_id", "value"),
    )
    def custom_cascading_filter(continent_selector_id_value):
        if not continent_selector_id_value:
            return [], None
        continent_df = df_gapminder[df_gapminder['continent'] == continent_selector_id_value]
        countries_list = list(set(continent_df['country'].tolist()))
        countries_list.sort()
        return countries_list, countries_list[0]

    page_country = vm.Page(
        title="Country Analysis",
        components=[
            vm.Table(
                id="table_country",
                title="Table Country",
                figure=dash_data_table(
                    data_frame=px.data.gapminder(),
                ),
            ),
        ],
        controls=[
            vm.Filter(
                id="continent_filter_id",
                column="continent",
                selector=vm.Dropdown(
                    id="continent_selector_id",
                    # value="Europe",
                    multi=False,
                    title="Select continent",
                ),
            ),
            vm.Filter(
                id="country_filter_id",
                column="country",
                selector=vm.Dropdown(
                    id="country_selector_id",
                    multi=True,
                    title="Select country",
                )
            ),
        ],
    )
    return page_country

dashboard = vm.Dashboard(
    pages=[
        create_country_analysis(),
    ],
)

if __name__ == "__main__":
    Vizro(assets_folder="../assets").build(dashboard).run()

I really hope this example can help you achieve the desired behaviour. Tell us if the solution works for you and if we can still help you somehow.

P.S. As @Joseph-Perkins already said, similar behaviour will soon be possible to implement just using the Vizro syntax (without needing to import dash library).

Et9797 commented 6 months ago

Hi @bvbvtw. It's possible to use Vizro in combination with the Dash which makes a requested feature possible.

Here's an example with the plotly.express.data.gapminder() data where the "country filter" options are filtered by "continent filter" selected value:

import dash
import pandas as pd
import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.tables import dash_data_table

def create_country_analysis():
    df_gapminder = px.data.gapminder()

    @dash.callback(
        dash.Output("country_selector_id", "options"),
        dash.Output("country_selector_id", "value"),
        dash.Input("continent_selector_id", "value"),
    )
    def custom_cascading_filter(continent_selector_id_value):
        if not continent_selector_id_value:
            return [], None
        continent_df = df_gapminder[df_gapminder['continent'] == continent_selector_id_value]
        countries_list = list(set(continent_df['country'].tolist()))
        countries_list.sort()
        return countries_list, countries_list[0]

    page_country = vm.Page(
        title="Country Analysis",
        components=[
            vm.Table(
                id="table_country",
                title="Table Country",
                figure=dash_data_table(
                    data_frame=px.data.gapminder(),
                ),
            ),
        ],
        controls=[
            vm.Filter(
                id="continent_filter_id",
                column="continent",
                selector=vm.Dropdown(
                    id="continent_selector_id",
                    # value="Europe",
                    multi=False,
                    title="Select continent",
                ),
            ),
            vm.Filter(
                id="country_filter_id",
                column="country",
                selector=vm.Dropdown(
                    id="country_selector_id",
                    multi=True,
                    title="Select country",
                )
            ),
        ],
    )
    return page_country

dashboard = vm.Dashboard(
    pages=[
        create_country_analysis(),
    ],
)

if __name__ == "__main__":
    Vizro(assets_folder="../assets").build(dashboard).run()

I really hope this example can help you achieve the desired behaviour. Tell us if the solution works for you and if we can still help you somehow.

P.S. As @Joseph-Perkins already said, similar behaviour will soon be possible to implement just using the Vizro syntax (without needing to import dash library).

Is this there a solution to this problem now without importing dash and using newly added Vizro custom actions?

petar-qb commented 6 months ago

Hi @Et9797! We don't yet support this feature natively in Vizro, but will let you know when we do.