«Выберите все» с выпадающим меню в черточке.

#python #drop-down-menu #plotly-dash

Вопрос:

Я работаю над учебником ниже: https://realpython.com/python-dash/ чтобы улучшить свои навыки в Dash.

Я пытаюсь изменить раскрывающееся меню выбора одного элемента с регионом с помощью раскрывающегося меню выбора нескольких элементов с:

  • Опция «Выбрать все»
  • Опция «Отменить выбор всех»

На данный момент я сделал:

 import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import numpy as np
from dash.dependencies import Output, Input

data = pd.read_csv("avocado.csv")
data["Date"] = pd.to_datetime(data["Date"], format="%Y-%m-%d")
data.sort_values("Date", inplace=True)

external_stylesheets = [
    {
        "href": "https://fonts.googleapis.com/css2?"
        "family=Lato:wght@400;700amp;display=swap",
        "rel": "stylesheet",
    },
]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = "Avocado Analytics: Understand Your Avocados!"

options_reg=[
    {"label": region, "value": region}
    for region in np.sort(data.region.unique())
    ]

app.layout = html.Div(
    children=[
        html.Div(
            children=[
                html.P(children="🥑", className="header-emoji"),
                html.H1(
                    children="Avocado Analytics", className="header-title"
                ),
                html.P(
                    children="Analyze the behavior of avocado prices"
                    " and the number of avocados sold in the US"
                    " between 2015 and 2018",
                    className="header-description",
                ),
            ],
            className="header",
        ),
        html.Div(
            children=[
                html.Div(
                    children=[
                        html.Div(children="Region", className="menu-title"),
                        dcc.Dropdown(
                            id="region-filter",
                            options=[{'label': 'Select all', 'value': 'all_values'}] options_reg,
                            value=['all_values'],
                            clearable=True,
                            multi=True, #Multi menu
                            className="dropdown",
                        )
                    ]
                ),
                html.Div(
                    children=[
                        html.Div(children="Type", className="menu-title"),
                        dcc.Dropdown(
                            id="type-filter",
                            options=[
                                {"label": avocado_type, "value": avocado_type}
                                for avocado_type in data.type.unique()
                            ],
                            value="organic",
                            clearable=False,
                            searchable=False,
                            className="dropdown",
                        ),
                    ],
                ),
                html.Div(
                    children=[
                        html.Div(
                            children="Date Range",
                            className="menu-title"
                            ),
                        dcc.DatePickerRange(
                            id="date-range",
                            min_date_allowed=data.Date.min().date(),
                            max_date_allowed=data.Date.max().date(),
                            start_date=data.Date.min().date(),
                            end_date=data.Date.max().date(),
                        ),
                    ]
                ),
            ],
            className="menu",
        ),
        html.Div(
            children=[
                html.Div(
                    children=dcc.Graph(
                        id="price-chart", config={"displayModeBar": False},
                    ),
                    className="card",
                ),
                html.Div(
                    children=dcc.Graph(
                        id="volume-chart", config={"displayModeBar": False},
                    ),
                    className="card",
                ),
            ],
            className="wrapper",
        ),
    ]
)


@app.callback(
    [Output("price-chart", "figure"), Output("volume-chart", "figure")],
    [
        Input("region-filter", "value"),
        Input("type-filter", "value"),
        Input("date-range", "start_date"),
        Input("date-range", "end_date"),
    ],
)
def update_charts(region, avocado_type, start_date, end_date):
    if region==['all_values']:
        mask = ((data.type == avocado_type)
                amp; (data.Date >= start_date)
                amp; (data.Date <= end_date)
                )
    else :
        mask = (
            (data.region.isin(region))
            amp; (data.type == avocado_type)
            amp; (data.Date >= start_date)
            amp; (data.Date <= end_date)
        )

    filtered_data = data.loc[mask, :]
    filtered_data["total price"]=filtered_data["AveragePrice"]*filtered_data["Total Volume"]
    filtered_data=pd.pivot_table(filtered_data,index=["Date","type","year"] ,values=["total price","Total Volume"],aggfunc={"total price":sum,"Total Volume":sum},fill_value=0).reset_index()#.droplevel(1, axis=1)
    filtered_data["AveragePrice"]=filtered_data["total price"]/filtered_data["Total Volume"]
    price_chart_figure = {
        "data": [
            {
                "x": filtered_data["Date"],
                "y": filtered_data["AveragePrice"],
                "type": "lines",
                "hovertemplate": "$%{y:.2f}<extra></extra>",
            },
        ],
        "layout": {
            "title": {
                "text": "Average Price of Avocados",
                "x": 0.05,
                "xanchor": "left",
            },
            "xaxis": {"fixedrange": True},
            "yaxis": {"tickprefix": "$", "fixedrange": True},
            "colorway": ["#17B897"],
        },
    }

    volume_chart_figure = {
        "data": [
            {
                "x": filtered_data["Date"],
                "y": filtered_data["Total Volume"],
                "type": "lines",
            },
        ],
        "layout": {
            "title": {"text": "Avocados Sold", "x": 0.05, "xanchor": "left"},
            "xaxis": {"fixedrange": True},
            "yaxis": {"fixedrange": True},
            "colorway": ["#E12D39"],
        },
    }
    return price_chart_figure, volume_chart_figure


if __name__ == "__main__":
    app.run_server(debug=True,port=8054)
 

Чтобы иметь возможность управлять выбором нескольких элементов, я вычисляю СУММУ и СРЕДНЕЕ ЗНАЧЕНИЕ с помощью сводной таблицы:

 @app.callback(
    [Output("price-chart", "figure"), Output("volume-chart", "figure")],
    [
        Input("region-filter", "value"),
        Input("type-filter", "value"),
        Input("date-range", "start_date"),
        Input("date-range", "end_date"),
    ],
)
def update_charts(region, avocado_type, start_date, end_date):
    if region==['all_values']:
        mask = ((data.type == avocado_type)
                amp; (data.Date >= start_date)
                amp; (data.Date <= end_date)
                )
    else :
        mask = (
            (data.region.isin(region))
            amp; (data.type == avocado_type)
            amp; (data.Date >= start_date)
            amp; (data.Date <= end_date)
        )
    #PIVOT TABLE
    filtered_data = data.loc[mask, :]
    filtered_data["total price"]=filtered_data["AveragePrice"]*filtered_data["Total Volume"]
    filtered_data=pd.pivot_table(filtered_data,index=["Date","type","year"] ,values=["total price","Total Volume"],aggfunc={"total price":sum,"Total Volume":sum},fill_value=0).reset_index()#.droplevel(1, axis=1)
    filtered_data["AveragePrice"]=filtered_data["total price"]/filtered_data["Total Volume"]
    price_chart_figure = {
        "data": [
            {
                "x": filtered_data["Date"],
                "y": filtered_data["AveragePrice"],
                "type": "lines",
                "hovertemplate": "$%{y:.2f}<extra></extra>",
            },
        ],
        "layout": {
            "title": {
                "text": "Average Price of Avocados",
                "x": 0.05,
                "xanchor": "left",
            },
            "xaxis": {"fixedrange": True},
            "yaxis": {"tickprefix": "$", "fixedrange": True},
            "colorway": ["#17B897"],
        },
    }
 

It works, but i’m wondering if there are another ways?

I coded the «Select all» option here :

         html.Div(
            children=[
                html.Div(children="Region", className="menu-title"),
                dcc.Dropdown(
                    id="region-filter",
                    options=[{'label': 'Select all', 'value': 'all_values'}] options_reg,
                    value=['all_values'],
                    clearable=True,
                    multi=True, #Multi menu
                    className="dropdown",
                )
            ]
        )
 

It works properly, but how can I manage the «Unselect all» option?