#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?