I am trying to pass input value to another with Dash Plot.
The main page has a list of strategies :
First_page = html.Div([
html.Div([dcc.Dropdown(id='strategy', options=[{'label': i, 'value': i} for i in [strat1, start2]], multi=True)], value = [strat1]),
html.Div([dcc.Input(id='date_start', type='text', value='1990-01-01')]),
html.Button('Start Calculation', id='button'),
])
And my pages 1 and 2 are the following :
for i in range(2) :
layout = html.Div([
html.Div([dcc.Dropdown(id='strategy'+str(i), options=[{'label': i, 'value': i} for i in [strat1, start2]]])], value = strat+str(i)),
html.Div([dcc.Input(id='date_start'+str(i), type='text', value='1990-01-01')]),
html.Button('Start Calculation', id='button'+str(i)),
+ other options not listed in main page
])
The goal is the following : when the user is on the main page he can choose the list of strategies he want to see, as well as the starting date.
Then when he press the button, it should open pages for each strategy selected (In the example we have 2 strategies so I should have 2 pages : localhost:port/page-strat1 and localhost:port/page-strat2) where the graph shown on each page starts with the selected date.
I succeed to open the pages localhost:port/strat1 and/or the page localhost:port/strat2 depending on the list of selected strategies.
list_event = [Event('button', 'click')]
list_state = [State('strategy', 'value')]
#app.callback(Output('hidden-div', 'children'),events=list_event, state=list_state)
def create_callback_share(datestart, list_strategies_used):
for _strat in list_strategies_used:
time.sleep(1)
webbrowser.open('http://localhost:port/page-'+_strat)
But I do not succeed to send the selected date. I try the following callback :
for i in range(2) :
#app.callback(Output('date_start'+str(i), 'value'),inputs=[Input('date_start', 'value')])
def set_display_children(selected_element):
return "{}".format(selected_element)
But the page localhost:port/strat1 and localhost:port/strat2 allow open with the default value which is '1990-01-01' even if I enter another value in the main page.
Is it possible to send value from one page to the other ?
Use dcc.Store() as in the answer here:
Plotly Dash Share Callback Input in another page with dcc.Store
And here is the Dash documentation:
https://dash.plotly.com/dash-core-components/store
Related
I have a Dash app with 2 Tabs and on one Tab I have an upload button while on the other Tab the uploaded dataset is being shown. After uploading the data, it is shown on the second tab but when I switch to the first Tab and come back again to the second Tab, the data table is not there anymore. I have tried using persistence and persistence-type but it doesn't work. Here is the code for the data table
#du.callback(
output=Output('output-datatable', 'children'),
id='upload-data',
)
def get_a_list(filenames):
data1=pd.read_excel(filenames[0])
return dash_table.DataTable(
data = data1.to_dict('records'),
columns = [{'name': i, 'id': i} for i in data1.columns],
page_size =15, persistence = True, persistence_type = 'memory')
Instead of persistence, use dcc.store
In the layout:
dcc.Store(id='store-data', data=[], storage_type='local')
Callback function:
#du.callback(
output=Output('store-data', 'data'),
input = Input(id='upload-data','children')
)
Also check out this video: https://www.youtube.com/watch?v=dLykSQNIM1E
I have two pages in dash plotly, and an index file who run the pages :
Index.py
Page 1
Page 2
I have a variable in page 1 which I want to pass it in page 2 and work with it. ( example of code)
Is it possible in Dash plotly ?
I saw somewhere that I can use Dcc.store, but how can I stock this variable in it ?
First_page = html.Div([
html.Div([dcc.Input(id='date_start', type='text', value='2021')]),
...
...
])
#app.callback(
Output('someoutput', 'children'),
[Input('someinput', 'value')])
#Uploading a certain table
#app.callback(
Output('datatable', 'data'),
Input('someinput', 'value'))
def function(somedata):
#Get the VARIABLE
...
...
variable= 12 (result of the operation in funtion)
How can I get the VARIABLE value (12) and inject it in page 2 please ?
Second_page = html.Div([
html.Div([dcc.Input(id='', type='text', value='')]),
...
...
])
#app.callback ()
def function_page2(somedata_page2):
#Work with the VARIABLE in first page
...
Thank you .
I am working on an NLP project analyzing the words spoken by characters in The Office. Part of this project involves making a network diagram of which characters talk to each other for a given episode.
This will be shown in a Dash app by allowing a user to select dropdowns for 4 parameters: season, episode, character1, and character2.
Here is a relevant snippet of my code so far:
#Import libraries
import pandas as pd
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
#Load data
sheet_url = 'https://docs.google.com/spreadsheets/d/18wS5AAwOh8QO95RwHLS95POmSNKA2jjzdt0phrxeAE0/edit#gid=747974534'
url = sheet_url.replace('/edit#gid=', '/export?format=csv&gid=')
df = pd.read_csv(url)
#Set parameters
choose_season = df['season'].unique()
choose_episode = df['episode'].unique()
choose_character = ['Andy','Angela', 'Darryl', 'Dwight', 'Jan', 'Jim','Kelly','Kevin','Meredith','Michael','Oscar','Pam','Phyllis','Roy','Ryan','Stanley','Toby']
#Define app layout
app = dash.Dash()
server = app.server
app.layout = html.Div([
dbc.Row([
dbc.Col(
dcc.Dropdown(
id='dropdown1',
options=[{'label': i, 'value': i} for i in choose_season],
value=choose_season[0]
), width=3
),
dbc.Col(
dcc.Dropdown(
id='dropdown2',
options=[{'label': i, 'value': i} for i in choose_episode],
value=choose_episode[0]
), width=3
),
dbc.Col(
dcc.Dropdown(
id='dropdown3',
options=[{'label': i, 'value': i} for i in choose_character],
value=choose_character[0]
), width=3
),
dbc.Col(
dcc.Dropdown(
id='dropdown4',
options=[{'label': i, 'value': i} for i in choose_character],
value=choose_character[1]
), width=3
)
])
])
if __name__=='__main__':
app.run_server()
In order to have this work efficiently, I would like to have the following dependencies in the dropdown menus:
1.) The selection of the first dropdown menu updates the dropdown menu
ie: Season updates possible episodes
2.) The selection of the first two dropdown menus updates the 3rd and 4th dropdown menus
ie: Season, Episode updates possible characters (if a character was not in that episode, they will not appear)
3.) The selection of the third dropdown menu updates the fourth dropdown menu
ie: If a character is selected in the third dropdown menu, they can not be selected in the fourth (can't select the same character twice)
I understand one way to do this is to make a massive season to episode dictionary and then an even larger season to episode to character dictionary.
I've already made the code to process the season to episode dictionary:
#app.callback(
Output('dropdown2', 'options'), #--> filter episodes
Output('dropdown2', 'value'),
Input('dropdown1', 'value') #--> choose season
)
def set_episode_options(selected_season):
return [{'label': i, 'value': i} for i in season_episode_dict[selected_season]], season_episode_dict[selected_season][0]
I can definitely build these dictionaries, but this seems like a really inefficient use of time. Does anyone know of a way to build these dictionaries with just a few lines of code? Not sure how to approach building these in the easiest way possible. Also, if you have an idea for a better way to approach this problem, please let me know that too.
Any help would be appreciated! Thank you!
I think I see what you're asking about now. Something like this should get you a basic dictionary, which you could then modify for the options param for the dropdowns.
df = pd.read_csv(url)
season_episode_character_dictionary = {}
for season in df['season'].unique.tolist():
df_season = df[df['season'].eq(season)]
season_episode_character_dictionary[season] = {}
for episode in df_season['episode'].unique.tolist():
df_episode = df_season[df_season['episode'].eq(episode)]
characters = df_episode['characters'].unique.tolist()
season_episode_character_dictionary[season][episode] = characters
I'm pretty confused by what 'children' even does in Dash html. Why does it even exist? Why would you use it? I tried reading the documentation, but it hasn't been very helpful.
With reference to the block of code below:
What does the children property even do in the first line?
Couldn't you replace children with something like 'figure' for the plots?
Block of Code:
app.layout = html.Div(children=[
# TODO1: Add title to the dashboard
html.H1("Airline Dashboard by CK", style = {'text-align':'center'}),
# REVIEW2: Dropdown creation
# Create an outer division
html.Div([
# Add an division
html.Div([
# Create an division for adding dropdown helper text for report type
html.Div(
[
html.H2('Report Type:', style={'margin-right': '2em'}),
]
),
# TODO2: Add a dropdown
dcc.Dropdown(id = 'input-type',
options = [{'label':'Yearly Airline Performance Report', 'value': 'OPT1'},
{'label':'Yearly Average Flight Delay Statistics', 'value': 'OPT2'}],
multi = False,
placeholder = 'Select a Report Type',
style={'width': '80%', 'padding': '3px', 'font-size': '20px', 'text-align-last': 'center'}
)
# Place them next to each other using the division style
], style={'display': 'flex'}),
# Add next division
html.Div([
# Create an division for adding dropdown helper text for choosing year
html.Div(
[
html.H2('Choose Year:', style={'margin-right': '2em'})
]
),
dcc.Dropdown(id='input-year',
# Update dropdown values using list comphrehension
options=[{'label': i, 'value': i} for i in year_list],
placeholder="Select a year",
style={'width': '80%', 'padding': '3px', 'font-size': '20px', 'text-align-last': 'center'}),
# Place them next to each other using the division style
], style={'display': 'flex'}),
]),
# Add Computed graphs
# REVIEW3: Observe how we add an empty division and providing an id that will be updated during callback
html.Div([], id='plot1'),
html.Div([
html.Div([], id='plot2'),
html.Div([], id='plot3')
], style={'display': 'flex'}),
# TODO3: Add a division with two empty divisions inside. See above disvision for example.
html.Div([
html.Div([], id='plot4'),
html.Div([], id='plot5')
], style = {'display':'flex'})
])
# Callback function definition
# TODO4: Add 5 ouput components
#app.callback(
[Input(component_id='input-type', component_property='value'),
Input(component_id='input-year', component_property='value')],
# REVIEW4: Holding output state till user enters all the form information. In this case, it will be chart type and year
[Output("plot1", 'children'), Output("plot2", "children"),
Output("plot3", "children"), Output("plot4", "children"),
Output("plot5", "children")
])
From this page of the docs:
The children property is special. By convention, it's always the first attribute which means that you can omit it: html.H1(children='Hello Dash') is the same as html.H1('Hello Dash'). Also, it can contain a string, a number, a single component, or a list of components.
Some components, such as html.Div and html.P, accept a value for their children prop. Others, such as dcc.Graph or dcc.Dropdown do not, and require other props in order to function properly.
As #KarlKnechtel mentioned in his comment, when one component is a child of another, it represents a nesting of the first component inside the other. The following are analogous:
In Dash:
html.Div(
children=[
html.H1('This is some text'),
html.P('This is also some text'),
]
)
In HTML:
<div>
<h1>This is some text</h1>
<p>This is also some text</p>
</div>
I hope that answers your questions.
Edit:
Adding style after children to this html.Div would allow you to change the styles of the Div, which may impact the styles of the components nested inside it, but that is not the purpose of the children prop. As the docs mention, you can either explicitly set children= whatever, or you can pass the same value in first, with no explicit key word argument, and Dash will treat that as the children prop. Either way, behind the scenes, the component is still receiving a value for its children property.
The purpose of the children property is to allow users to nest components, just as we do in raw HTML. Without the children prop, it would not be possible to do things like group related items together by containing them in the same parent element (ex. putting navigation items inside a top navigation bar).
Ok so I'm trying to make simple webapp with dash plotly. I have a couple of plots on my dashboard that I need to be modified by the same dropdown. One plot is a lineplot that shows how the data fluctuates in a 5 year period and the other is an animated barchart that shows the selected country's move for certain year.
The data is in shape:
Country name
Score
year
Finland
12
2015
Finland
11
2016
Denmark
3
2015
And so on for 150 countries and a period from 2015-2020
Here is my code:
#app.callback(
Output("page-content", "children"),
[Input("url", "pathname")]
)
def render_page_content(pathname):
if pathname == "/":
return [
html.P("This is the content of the home page!"),
#This is the code for the plots
dcc.Graph(id='scattergraph', figure=fig),
html.Div([
html.Div([
dcc.Graph(id='linechart'),
],className='six columns'),
html.Div([
dcc.Graph(id='barchart'),
],className='six columns'),
],className='row'),
html.Div([
dcc.Dropdown(id='dropdown_id', options=name_options,multi=True)],style={'width':'40%'})
]
elif pathname == "/page-1":
return html.P("This is the content of page 1. Yay!")
elif pathname == "/page-2":
return html.P("Oh cool, this is page 2!")
# If the user tries to reach a different page, return a 404 message
return dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname {pathname} was not recognised..."),
]
)
And below is the function to update the output, along with a screenshot of the result
#app.callback(
[Output('piechart', 'figure'),
Output('barchart', 'figure')],
[Input('dropdown_id', 'value')]
)
#This updates the charts on the bottom of the home page
def update_data(chosen_country):
# if len(chosen_country)==0:
# df_filterd = dff[dff['Country name'].isin(['Netherlands','Iran','Spain','Italy'])]
# else:
# print(chosen_country)
# df_filterd = dff[dff.index.isin(chosen_country)]
dff=df.copy()
df_filterd = dff[dff['Country name']== chosen_country]
bar_chart=px.bar(data_frame=df_filterd, x="Country name", y="Score", color="Country name",animation_frame="year")
list_chosen_countries=df_filterd['Country name'].tolist()
df_line = dfcon[dfcon['Country name'].isin(list_chosen_countries)]
line_chart = px.line(
data_frame=df_line,
x='year',
y='Score',
color='Country name',
labels={'Country name':'Countries', 'year':'year'},
)
line_chart.update_layout(uirevision='foo')
return (bar_chart,line_chart)
Some questions I can't really see in your code:
Where is the DataFrame dfcon defined?
Where is the variable name_options defined? Have you assigned the labels and values for the drop down menu? You could do something like:
dcc.Dropdown(id='dropdown_id',
options={'label': name, 'value': name} for name in name_options,
multi=True)
Then the value of the dropdown will come into the callback! Be careful with your multi being True, if the user is allowed to pick more than one country then it could have issues when you are filtering the information, so you would need a new for loop.