I want to get from a call back a DF(DataFrame) and the figure for that same DF, but I want to show each one individually.
I will take this example posted by #Philippe in this link just to have something to work with and give some ideas:
import dash
import dash_core_components as dcc
import dash_table as dt
import dash_html_components as html
from dash.dependencies import Output, Input
from dash.exceptions import PreventUpdate
import plotly.graph_objs as go
sample_data = {
'series': {
'data': [
{'title': 'Game of Thrones', 'score': 9.5},
{'title': 'Stranger Things', 'score': 8.9},
{'title': 'Vikings', 'score': 8.6}
],
'style': {
'backgroundColor': '#ff998a'
}
},
'movies': {
'data': [
{'title': 'Rambo', 'score': 7.7},
{'title': 'The Terminator', 'score': 8.0},
{'title': 'Alien', 'score': 8.5}
],
'style': {
'backgroundColor': '#fff289'
}
}
}
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1('Multi output example'),
dcc.Dropdown(id='data-dropdown', options=[
{'label': 'Movies', 'value': 'movies'},
{'label': 'Series', 'value': 'series'}
], value='movies'),
html.Div([
dcc.Graph(id='graph'),
dt.DataTable(id='data-table', columns=[
{'name': 'Title', 'id': 'title'},
{'name': 'Score', 'id': 'score'}
])
])
], id='container')
#app.callback([
Output('graph', 'figure'),
Output('data-table', 'data'),
Output('data-table', 'columns'),
Output('container', 'style')
], [Input('data-dropdown', 'value')])
def multi_output(value):
if value is None:
raise PreventUpdate
selected = sample_data[value]
data = selected['data']
columns = [
{'name': k.capitalize(), 'id': k}
for k in data[0].keys()
]
figure = go.Figure(
data=[
go.Bar(x=[x['score']], text=x['title'], name=x['title'])
for x in data
]
)
return figure, data, columns, selected['style']
if __name__ == '__main__':
app.run_server()
In the end a results showing the fig and data of the DataFrame is shown
like this.
However, I want to first show the figure. Then I want to use the data from the DF created in the callback to do more calculations and finally display those calculations using a submit button you click on it.
Is this possible?
What I have done so far is using two different callbacks with kind of the same script, but I was wondering if I can used just one callback a save some repetition in the code.
I hope my question is clear, and thank you in advance!
I found a solution!I used dcc.store here some references if someone need it in the future: https://dash.plotly.com/dash-core-components/store
My line code was this one:
dcc.Store(id='store-data', data=[], storage_type='memory'),
Taking from https://www.youtube.com/watch?v=dLykSQNIM1E. Great video created by Youtube Channel: Charming Data
Related
I am trying to create a simple networkx and dash dashboard with a dropdown to select either successors, predecessors, or connected then when I click on a node it will return that info.
For example, if I select predecessors and then click on Texas, it will provide US, but if I select successors and click on it, it will show Houston.
If I select connected and click on Texas, it will respond with US and Houston.
Would anyone know the correct callback function that I would need to create to accomplish this?
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_cytoscape as cyto
from dash.dependencies import Input, Output
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
html.P("Dash Cytoscape:"),
cyto.Cytoscape(
id='cytoscape',
elements=[
{'data': {'id': 'ca', 'label': 'Canada'}},
{'data': {'id': 'on', 'label': 'Ontario'}},
{'data': {'id': 'qc', 'label': 'Quebec'}},
{'data': {'id': 'us', 'label': 'US'}},
{'data': {'id': 'ny', 'label': 'New York'}},
{'data': {'id': 'tx', 'label': 'Texas'}},
{'data': {'id': 'fl', 'label': 'Florida'}},
{'data': {'id': 'mia', 'label': 'Miami'}},
{'data': {'id': 'hou', 'label': 'Houston'}},
{'data': {'source': 'ca', 'target': 'on'}},
{'data': {'source': 'ca', 'target': 'qc'}},
{'data': {'source': 'us', 'target': 'ny'}},
{'data': {'source': 'us', 'target': 'tx'}},
{'data': {'source': 'us', 'target': 'fl'}},
{'data': {'source': 'tx', 'target': 'hou'}},
{'data': {'source': 'fl', 'target': 'mia'}}
],
layout = {'name':'breadthfirst', 'directed':True},
style={'width': '400px', 'height': '500px'}
)
])
#app.callback(Output('cytoscape-tapNodeData-output', 'children'),
Input('cytoscape-event-callbacks-2', 'tapNodeData'))
def displayTapNodeData(data):
if data:
return
app.run_server(debug=True)
I add the necessary callback to make the dropdown menu working along with the clicking on the nodes. You need only to manipulate how to extract the data from the list edges and nodes in the callback function, and it will be pure python problem, and you can use directly the edges and nodes list inside the callback function without passing them as parameters.
import dash
import dash_cytoscape as cyto
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
nodes = [
{
'data': {'id': short, 'label': label},
}
for short, label in (
('la', 'Los Angeles'),
('nyc', 'New York'),
('to', 'Toronto'),
('mtl', 'Montreal'),
('van', 'Vancouver'),
('chi', 'Chicago'),
('bos', 'Boston'),
('hou', 'Houston')
)
]
edges = [
{'data': {'source': source, 'target': target}}
for source, target in (
('van', 'la'),
('la', 'chi'),
('hou', 'chi'),
('to', 'mtl'),
('mtl', 'bos'),
('nyc', 'bos'),
('to', 'hou'),
('to', 'nyc'),
('la', 'nyc'),
('nyc', 'bos')
)
]
default_stylesheet = [
{
'selector': 'node',
'style': {
'background-color': '#BFD7B5',
'label': 'data(label)'
}
}
]
app.layout = html.Div([
cyto.Cytoscape(
id='cytoscape',
layout={'name':'breadthfirst','directed':True},
elements=edges+nodes,
stylesheet=default_stylesheet,
style={'width': '100%', 'height': '450px'}
),
html.Div([
dcc.Dropdown(['predecessors', 'successors', 'connected'], 'predecessors', id='cyto-dropdown')
]),
html.Div(id='my-output'),
])
#app.callback(Output('my-output', 'children'),
[Input('cyto-dropdown', 'value'),
Input('cytoscape', 'tapNodeData')])
def displayTapNodeData(value, data):
if data:
if value == 'successors':
return "The successor node(s): " + data['id']
elif value == 'predecessors':
return "The predecessor node(s) " + data['id']
elif value == 'connected':
return "The connected node(s): " + data['id']
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
I am trying to create a dashboard to show the ethnicity makeup in different cities for multiple years. My dataframe consists of Year, Month, City and Native variables. I pasted an image on the bottom that shows my dataframe. I also tried to replicate a Dash code that I have but I received multiple errors after executing it, and it looks like most of the errors are about the City variable. Is there any guide to get my dash to work?
import dash
from jupyter_dash import JupyterDash # pip install dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
#df
import dash
from jupyter_dash import JupyterDash # pip install dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
#df
app = JupyterDash()
app.layout = html.Div([
html.H1("Native Country of Father"),
dcc.Dropdown(
id='cities',
options=[{'label': i, 'value': i} for i in list(df.City.unique()) + ['All']],
value='All'
),
dcc.RadioItems(
id='xaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Log',
labelStyle={'display': 'inline-block'}
),
dcc.Graph(id='graph-with-slider'),
dcc.Slider(
id='year-slider',
min=df['Year'].min(),
max=df['Year'].max(),
value=df['Year'].min(),
step=None,
marks={str(Year): str(Year) for Year in df['Year'].unique()}
)
],
style={'width': '48%', 'display': 'inline-block'})
#app.callback(
Output('graph-with-slider', 'figure'),
[Input('year-slider', 'value'),
Input('xaxis-type','value'),
Input('cities','value')])
def update_figure(selected_year, axis_type, City):
if City=="All":
filtered_df = df
else:
filtered_df = df[df['City']==City]
filtered_df = filtered_df[filtered_df.Year == selected_year]
traces = []
for i in filtered_df.City.unique():
df_by_City = filtered_df[filtered_df['City'] == i]
traces.append(go.Scatter(
y=df_by_City['Native Country of Father'],
text=df_by_City['Native Country of Father'],
mode='markers',
opacity=0.7,
marker={
'size': 15,
'line': {'width': 0.5, 'color': 'white'}
},
name=i
))
return {
'data': traces,
'layout': go.Layout(
xaxis={'type': 'linear' if axis_type == 'Linear' else 'log',
'title': 'GDP Per Capita'},
yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
legend={'x': 0, 'y': 1},
hovermode='closest'
)
}
if __name__ =='__main__':
app.run_server(mode="external")
To get the dropdown working properly, you'll have to fix the value passed to options. What you have is:
options=[{'label': i, 'value': i} for i in list(df.City.unique()) + ['All']]
If you remove ['All'] and change the value prop, it should work. In order to have a value that selects everything, you need something like
options=[
{'label': i, 'value': i} for i in list(df.City.unique())
] + [{'label': 'All', 'value': 'All'}]
I'm building a dashboard (code below) and my goal is to show several key facts about the data on a country-level basis. For example, current population vs. average population of all countries, life expectation vs. average life expectation of all countries etc.
I don't want to display the graph when no country (i.e. no dropdown option) is selected. This should also be standard when first launching the dashboard. However, I receive an error message when either clearing the dropdown or setting the value to '' in the layout area.
Does anybody know any solution to this problem?
import pandas as pd
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')
fig = go.Figure()
# create the Dash app
app = dash.Dash()
# set up app layout
app.layout = html.Div(children=[
html.H1(children='Demographic Statistics'),
dcc.Dropdown(id='country-dropdown',
options=[{'label': x, 'value': x}
for x in df.country.unique()],
value='Argentina',
multi=False, clearable=True),
dcc.Graph(id='indicators', figure=fig)
])
# set up the callback function
#app.callback(
Output('indicators', 'figure'),
[Input('country-dropdown', 'value')])
def display_demographic_statistics(selected_country):
filtered_country = df[df.country == selected_country]
pop_confirmed = df.loc[df['country'] == selected_country, 'pop'].iloc[0]
lifexp = df.loc[df['country'] == selected_country, 'lifeExp'].iloc[0]
average_confirmed = df["pop"].mean()
average_lifexp = df["lifeExp"].mean()
return {
'data': [go.Indicator(
mode='number+delta',
value=pop_confirmed,
delta={'reference': average_confirmed,
'position': 'right',
'valueformat': ',g',
'relative': False,
'font': {'size': 15}},
number={'valueformat': ',',
'font': {'size': 20},
},
domain={'y': [0, 1], 'x': [0, 1]})],
'layout': go.Layout(
title={'text': 'Demgraphic Statistics'},
grid = {'rows': 2, 'columns': 2, 'pattern': "independent"},
template = {'data' : {'indicator': [{
'mode' : "number+delta+gauge",
'delta' : {'reference': 90}}]}}
),
}
# Run local server
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
You could make the component with id='indicators' an html.Div and use the callback to update its children property as follows:
if the user selects a country from the dropdown, then the callback returns
a dcc.Graph with the indicators for the selected country,
if the user clears the dropdown, then the callback returns None (i.e. nothing).
Note also that the value of the dropdown when no selection has been made is None, not ''.
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')
app = dash.Dash()
app.layout = html.Div(children=[
html.H1(children='Demographic Statistics'),
dcc.Dropdown(
id='country-dropdown',
options=[{'label': x, 'value': x} for x in df.country.unique()],
value=None,
multi=False,
clearable=True
),
html.Div(id='indicators')
])
#app.callback(
Output('indicators', 'children'),
[Input('country-dropdown', 'value')])
def display_demographic_statistics(selected_country):
if selected_country is not None:
pop_confirmed = df.loc[df['country'] == selected_country, 'pop'].iloc[0]
average_confirmed = df['pop'].mean()
return dcc.Graph(
figure=go.Figure(
data=go.Indicator(
mode='number+delta',
value=pop_confirmed,
delta={
'reference': average_confirmed,
'position': 'right',
'valueformat': ',g',
'relative': False,
'font': {'size': 15}
},
number={
'valueformat': ',',
'font': {'size': 20},
},
domain={
'y': [0, 1],
'x': [0, 1]
}
),
layout=go.Layout(
title={'text': 'Demgraphic Statistics'},
grid={'rows': 2, 'columns': 2, 'pattern': 'independent'},
template={'data': {'indicator': [{'mode': 'number+delta+gauge', 'delta': {'reference': 90}}]}}
)
)
)
else:
return None
if __name__ == '__main__':
app.run_server(host='127.0.0.1', debug=True)
I copied this code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_cytoscape as cyto
from dash.dependencies import Input, Output
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
html.P("Dash Cytoscape:"),
cyto.Cytoscape(
id='cytoscape',
elements=[
{'data': {'id': 'ca', 'label': 'Canada'}},
{'data': {'id': 'on', 'label': 'Ontario'}},
{'data': {'id': 'qc', 'label': 'Quebec'}},
{'data': {'source': 'ca', 'target': 'on'}},
{'data': {'source': 'ca', 'target': 'qc'}}
],
layout={'name': 'breadthfirst'},
style={'width': '400px', 'height': '500px'}
)
])
app.run_server(debug=True)
How do I add directed edges in this graph? I have seen examples online and they all add Matplotlib and Plotly to it. I want to change it with minimal changes. Is there any way for that?
I'm not sure if you are talking about making your layout (i) directed or to have (ii) edge arrows (or both) :
(i) You can add the parameter 'directed':True to your layout. The new layout would be:
layout = {'name':'breadthfirst', 'directed':True}
Other available parameters can be checked on the Cytoscape JavaSript documentation -> https://js.cytoscape.org/
(ii) You can check an example for Edge Arrows on Dash_cytoscape documentation -> https://dash.plotly.com/cytoscape/styling
You can add the source-arrow-shape or target-arrow-shape attribute inside the style object as the following example:
{'selector': '#BA',
'style': {
'source-arrow-color': 'red',
'source-arrow-shape': 'triangle',
'line-color': 'red'
}
},
I am trying to run simple code using PyCharm IDE but find this error:
Traceback (most recent call last):
File "D:/Tooling/untitled/SAS.py", line 37, in <module>
#app.callback(Output('my-graph', 'figure'),
File "C:\Users\mwx825326\AppData\Local\Programs\Python\Python38-32\lib\site-packages\dash\dash.py", line 886, in callback
self._validate_callback(output, inputs, state)
File "C:\Users\mwx825326\AppData\Local\Programs\Python\Python38-32\lib\site-packages\dash\dash.py", line 652, in _validate_callback
raise exceptions.LayoutIsNotDefined('''
dash.exceptions.LayoutIsNotDefined:
Attempting to assign a callback to the application but
the `layout` property has not been assigned.
Assign the `layout` property before assigning callbacks.
Alternatively, suppress this warning by setting
`app.config['suppress_callback_exceptions']=True`
and this is my Code:
import os
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
#from app import app
from dash.dependencies import Input, Output
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv('MNM_Rotterdam_5_Daily_Details-20191216081027.csv', error_bad_lines=False)
df['Date'] = pd.to_datetime(df.Date, infer_datetime_format=True)
if 'DYNO' in os.environ:
app_name = os.environ['DASH_APP_NAME']
else:
app_name = 'dash-timeseriesplot'
layout = html.Div([html.H1("GSM", style={'textAlign': 'center'}),
dcc.Dropdown(id='my-dropdown',options=[{'label': 'Voice_SetupFailRate_2G', 'value': 'Voice_SetupFailRate_2G'},{'label': 'Voice_DropRate_2G', 'value': 'Voice_DropRate_2G'},{'label': 'OutgHandover_SuccesRate_2G', 'value': 'OutgHandover_SuccesRate_2G'},{'label': 'Packet_SetupFailRate_2G', 'value': 'Packet_SetupFailRate_2G'},{'label': 'Packet_DLMBytes_2G', 'value': 'Packet_DLMBytes_2G'},{'label': 'Availability_2G', 'value': 'Availability_2G'}],
multi=True,value=['Voice_SetupFailRate_2G'],style={"display": "block","margin-left": "auto","margin-right": "auto","width": "60%"}),
dcc.Graph(id='my-graph')
], className="container")
#app.callback(Output('my-graph', 'figure'),
[Input('my-dropdown', 'value')])
def update_graph(selected_dropdown_value):
dropdown = {"Voice_SetupFailRate_2G": "Voice_SetupFailRate_2G","Voice_DropRate_2G": "Voice_DropRate_2G","OutgHandover_SuccesRate_2G": "OutgHandover_SuccesRate_2G","Packet_SetupFailRate_2G": "Packet_SetupFailRate_2G","Packet_DLMBytes_2G": "Packet_DLMBytes_2G","Availability_2G": "Availability_2G"}
trace1 = []
trace2 = []
for GSM in selected_dropdown_value:
trace1.append(go.Scatter(x=df[df["GSM"] == GSM]["Date"],y=df[df["GSM"] == GSM]["Open"],mode='lines',
opacity=0.7,name=f'Open {dropdown[GSM]}',textposition='bottom center'))
trace2.append(go.Scatter(x=df[df["GSM"] == GSM]["Date"],y=df[df["GSM"] == GSM]["Close"],mode='lines',
opacity=0.6,name=f'Close {dropdown[GSM]}',textposition='bottom center'))
traces = [trace1, trace2]
data = [val for sublist in traces for val in sublist]
figure = {'data': data,
'layout': go.Layout(colorway=["#5E0DAC", '#FF4F00', '#375CB1', '#FF7400', '#FFF400', '#FF0056'],
height=600,title=f"Opening and Closing Prices for {', '.join(str(dropdown[i]) for i in selected_dropdown_value)} Over Time",
xaxis={"title":"Date",
'rangeselector': {'buttons': list([{'count': 1, 'label': '1M', 'step': 'month', 'stepmode': 'backward'},
{'count': 6, 'label': '6M', 'step': 'month', 'stepmode': 'backward'},
{'step': 'all'}])},
'rangeslider': {'visible': True}, 'type': 'date'},yaxis={"title":"Price (USD)"})}
return figure
if __name__ == '__main__':
app.run_server(debug=True)
So any one have a solution for this...
So anyone have a solution for this error?
I think the cyntax of code it doesn't work with the PyCharm IDE??
I am trying to figure where's the problem exactly, but I fail on this :(..
I am Glad if any one could help me :)...
Before defining your callback you need to assign your defined layout to the app. Before #app.callback .. add the following: app.layout = layout. Alternatively, you can do as Frayal mentioned, simply replace
layout = html.Div([html.H1("GSM", style={'textAlign': 'center'}),
dcc.Dropdown(id='my-dropdown',options=[{'label': 'Voice_SetupFailRate_2G', 'value': 'Voice_SetupFailRate_2G'},{'label': 'Voice_DropRate_2G', 'value': 'Voice_DropRate_2G'},{'label': 'OutgHandover_SuccesRate_2G', 'value': 'OutgHandover_SuccesRate_2G'},{'label': 'Packet_SetupFailRate_2G', 'value': 'Packet_SetupFailRate_2G'},{'label': 'Packet_DLMBytes_2G', 'value': 'Packet_DLMBytes_2G'},{'label': 'Availability_2G', 'value': 'Availability_2G'}],
multi=True,value=['Voice_SetupFailRate_2G'],style={"display": "block","margin-left": "auto","margin-right": "auto","width": "60%"}),
dcc.Graph(id='my-graph')
], className="container")
by
app.layout = html.Div([html.H1("GSM", style={'textAlign': 'center'}),
dcc.Dropdown(id='my-dropdown',options=[{'label': 'Voice_SetupFailRate_2G', 'value': 'Voice_SetupFailRate_2G'},{'label': 'Voice_DropRate_2G', 'value': 'Voice_DropRate_2G'},{'label': 'OutgHandover_SuccesRate_2G', 'value': 'OutgHandover_SuccesRate_2G'},{'label': 'Packet_SetupFailRate_2G', 'value': 'Packet_SetupFailRate_2G'},{'label': 'Packet_DLMBytes_2G', 'value': 'Packet_DLMBytes_2G'},{'label': 'Availability_2G', 'value': 'Availability_2G'}],
multi=True,value=['Voice_SetupFailRate_2G'],style={"display": "block","margin-left": "auto","margin-right": "auto","width": "60%"}),
dcc.Graph(id='my-graph')
], className="container")
you need to assign the layout to the application: replace layout by app.layout