mckinsey / vizro

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

Parameters as dictionary of label-value mappings not working in custom chart when "ALL" selected #557

Closed GiulioMorinaQB closed 10 hours ago

GiulioMorinaQB commented 4 days ago

Description

When using a custom figure and setting options for a parameter using a dictionary, when "ALL" is selected no data is displayed.

Expected behavior

No response

Which package?

vizro

Package version

0.1.18

Python version

3.9

OS

MacOS

How to Reproduce

import pandas as pd
from vizro import Vizro
import vizro.plotly.express as px
import vizro.models as vm
from vizro.models.types import capture

df_stocks = px.data.stocks(datetimes=True)

df_stocks_long = pd.melt(
    df_stocks,
    id_vars='date',
    value_vars=['GOOG', 'AAPL', 'AMZN', 'FB', 'NFLX', 'MSFT'],
    var_name='stocks',
    value_name='value'
)

@capture("graph")
def vizro_plot(data_frame, stocks_selected, **kwargs):
    return px.line(data_frame[data_frame["stocks"].isin(stocks_selected)], **kwargs)

df_stocks_long['value'] = df_stocks_long['value'].round(3)

page = vm.Page(
    title="My first page",
    components=[
        vm.Graph(id="my_graph", figure=vizro_plot(data_frame=df_stocks_long, stocks_selected=list(df_stocks_long["stocks"].unique()), x="date", y="value", color="stocks")),
    ],
    controls=[
        vm.Parameter(
            targets=["my_graph.stocks_selected"],
            selector=vm.Dropdown(
                options=[{'label': s, 'value': s} for s in df_stocks_long["stocks"].unique()],
            ),
        ),
        vm.Filter(column="value"),
        vm.Filter(column="date"),
    ],
)

dashboard = vm.Dashboard(pages=[page])

Vizro().build(dashboard).run()

Output

Screenshot 2024-07-01 at 15 36 41

Code of Conduct

lingyielia commented 4 days ago

Hi @GiulioMorinaQB , thanks for raising the bug report! We are investigating it and will come back to you once we find the root cause. Meanwhile, you can config your parameter and custom chart in two ways: Approach 1:

import pandas as pd
from vizro import Vizro
import vizro.plotly.express as px
import vizro.models as vm
from vizro.models.types import capture
from typing import List, Dict, Union
df_stocks = px.data.stocks(datetimes=True)

df_stocks_long = pd.melt(
    df_stocks,
    id_vars='date',
    value_vars=['GOOG', 'AAPL', 'AMZN', 'FB', 'NFLX', 'MSFT'],
    var_name='stocks',
    value_name='value'
)

@capture("graph")
def vizro_plot(data_frame, stocks_selected: Union[List[Dict], List], **kwargs):
    if isinstance(stocks_selected, list) and all(isinstance(i, dict) for i in stocks_selected):
        full_options = [stock['label'] for stock in stocks_selected]
        return px.line(data_frame[data_frame["stocks"].isin(full_options)], **kwargs)
    else:
        return px.line(data_frame[data_frame["stocks"].isin(stocks_selected)], **kwargs)

df_stocks_long['value'] = df_stocks_long['value'].round(3)

page = vm.Page(
    title="My first page",
    components=[
        vm.Graph(id="my_graph", figure=vizro_plot(data_frame=df_stocks_long, stocks_selected=[{'label': s, 'value': s} for s in df_stocks_long["stocks"].unique()], x="date", y="value", color="stocks")),
    ],
    controls=[
        vm.Parameter(
            targets=["my_graph.stocks_selected"],
            selector=vm.Dropdown(
                options=[{'label': s, 'value': s} for s in df_stocks_long["stocks"].unique()],
            ),
        ),
    ],
)

dashboard = vm.Dashboard(pages=[page])

In this case, the custom chart can accept either List[Dict] or simple List.

Approach 2:

import pandas as pd
from vizro import Vizro
import vizro.plotly.express as px
import vizro.models as vm
from vizro.models.types import capture
from typing import List

df_stocks = px.data.stocks(datetimes=True)

df_stocks_long = pd.melt(
    df_stocks,
    id_vars='date',
    value_vars=['GOOG', 'AAPL', 'AMZN', 'FB', 'NFLX', 'MSFT'],
    var_name='stocks',
    value_name='value'
)

@capture("graph")
def vizro_plot(data_frame, stocks_selected: List, **kwargs):
    return px.line(data_frame[data_frame["stocks"].isin(stocks_selected)], **kwargs)

df_stocks_long['value'] = df_stocks_long['value'].round(3)

page = vm.Page(
    title="My first page",
    components=[
        vm.Graph(id="my_graph", figure=vizro_plot(data_frame=df_stocks_long, stocks_selected=list(df_stocks_long["stocks"].unique()), x="date", y="value", color="stocks")),
    ],
    controls=[
        vm.Parameter(
            targets=["my_graph.stocks_selected"],
            selector=vm.Dropdown(
                options=df_stocks_long["stocks"].unique().tolist(),
            ),
        ),
        vm.Filter(column="value"),
        vm.Filter(column="date"),
    ],
)

dashboard = vm.Dashboard(pages=[page])

Vizro().build(dashboard).run()

This approach use list as options, so it won't work if you need to label your values