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'}]
Related
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 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
I am working on example that you should be able to run,
as you can see everything looks fine, but when i am trying to apply this on my example where i have dates in this format : 20-08-2019 (%d-%m-%y)
Dash slider not working, i've tried to convert this df['year'] using to_datetime, any many others conversions but i am still receiving error:
Invalid argument `value` passed into Slider with ID "year-slider".
Expected `number`.
Was supplied type `string`.
Value provided: "2018-08-24T00:00:00"
code:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
df = pd.read_csv(
'https://raw.githubusercontent.com/plotly/'
'datasets/master/gapminderDataFiveYear.csv')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Graph(id='graph-with-slider'),
dcc.Slider(
id='year-slider',
min=df['year'].min(),
max=df['year'].max(),
value=df['year'].min(),
marks={str(year): str(year) for year in df['year'].unique()},
step=None
)
])
#app.callback(
Output('graph-with-slider', 'figure'),
[Input('year-slider', 'value')])
def update_figure(selected_year):
filtered_df = df[df.year == selected_year]
traces = []
for i in filtered_df.continent.unique():
df_by_continent = filtered_df[filtered_df['continent'] == i]
traces.append(go.Scatter(
x=df_by_continent['gdpPercap'],
y=df_by_continent['lifeExp'],
text=df_by_continent['country'],
mode='markers',
opacity=0.7,
marker={
'size': 15,
'line': {'width': 0.5, 'color': 'white'}
},
name=i
))
return {
'data': traces,
'layout': go.Layout(
xaxis={'type': '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(debug=True)
Dash Slider objects only deal with int/float, so you will need to first convert the dates to int, such as Unix/epoch timestamps and then map the labels to whichever str date format you wish.
The example you provided works with the current version of dash 1.1.1 so - without a working example at hand - I will do some guesswork here. Assuming that you are using pandas and numpy, based on the example you provided, this should work:
import numpy as np
df['epoch_dt'] = df['year'].astype(np.int64) // 1e9
dcc.Slider(
id='year-slider',
min=df['epoch_dt'].min(),
max=df['epoch_dt'].max(),
value=df['epoch_dt'].min(),
marks={str(epoch): str(year) for epoch, year in df[['epoch_dt', 'year']].drop_duplicates().set_index('epoch_dt')['year'].to_dict()},
step=None
)
Hey guys,
I’m an intern python developer and I just found out about dash and Plotly, its amazing!
For my app I’m using a dataset containing info about fortune 500’s revenue in 1955-2005 period.
The problem I have is that the graph won’t update itself upon selecting additional company from the dropdown list, however, if I select a new company and delete a previous one - then the graph updates. It seems like something prevents the graph to show multiple lines at once. Also, is there any way I could add the legend telling which color is what company? Below is my code:
import dash
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
#Read CSV and change col. names
df = pd.read_csv('fortune500-full.csv')
df.columns = ['Year', 'Rank', 'Company', 'Revenue', 'Profit']
#Get a list of unique company names
Companies = df['Company'].unique()
#Stylesheet
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
#App layout
app.layout = html.Div([
#Dropdown
html.Div([
html.Label('Dropdown'),
dcc.Dropdown(
id = 'Dropdown',
options=[{'label': i, 'value': i} for i in Companies],
value=["General Motors"],
multi = True
),]),
#Graph
dcc.Graph(
id='Graph',
figure={
'data': [
go.Scatter(
x=df.loc[df['Company'] == i, 'Year'],
y=df.loc[df['Company'] == i, 'Revenue'],
text =df.loc[df['Company'] == i, 'Company'],
mode='lines',
name=i
) for i in df.Company.unique()],
'layout': go.Layout(
xaxis={'title': 'Year'},
yaxis={'title': 'Revenue'},
margin={'l': 50, 'b': 30, 't': 10, 'r': 0},
legend={'x': 1, 'y': 1},
hovermode='closest'
)}),
html.Div(dcc.RangeSlider(
id='Slider',
min=df['Year'].min(),
max=df['Year'].max(),
value=[1955, 2005],
marks={str(year): str(year) for year in df['Year'].unique()}
), style={'width': '98%', 'padding': '0px 20px 20px 20px'}),
html.Div(id='Output_slider',
style={'textAlign': 'center', 'color': ['#7FDBFF']}
)])
#app.callback(
dash.dependencies.Output('Graph', 'figure'),
[dash.dependencies.Input('Dropdown', 'value')])
def callback_a(dropdown_value):
trace = []
for val in dropdown_value:
trace.append(
go.Scatter(
x=df.loc[df['Company'] == val, 'Year'],
y=df.loc[df['Company'] == val, 'Revenue'],
text =df.loc[df['Company'] == val, 'Company'],
mode='lines',
name=val
),)
layout = go.Layout(
xaxis={'title': 'Year'},
yaxis={'title': 'Revenue'},
margin={'l': 50, 'b': 30, 't': 10, 'r': 0},
legend={'x': 1, 'y': 1},
hovermode='closest'
)
figure = {'data': trace, 'layout': layout}
return figure
#app.callback(
dash.dependencies.Output('Output_slider', 'children'),
[dash.dependencies.Input('Slider', 'value')])
def update_output(value):
return 'Wybrane lata: "{}"'.format(value)
#App
if __name__ == '__main__':
app.run_server(debug=True)
Could any of you please take a look at this and help me find root of this problem?
Kind regards.
I am attempting to create an interactive graph inside of the Dash framework. I am new to this type of setup and as a result I am starting off simple by recreating the "More About Visualizations" scatter plot found in the getting started guide with the slight addition of also adding a lowess regression. The desired outcome is that the sample graph remains identical with the fitted regression added. The code I have is:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import statsmodels.api as sm
app = dash.Dash()
df = pd.read_csv(
'https://gist.githubusercontent.com/chriddyp/' +
'5d1ea79569ed194d432e56108a04d188/raw/' +
'a9f9e8076b837d541398e999dcbac2b2826a81f8/'+
'gdp-life-exp-2007.csv')
performance_line = pd.DataFrame(sm.nonparametric.lowess(df['life expectancy'], df['gdp per capita'], frac=0.75))
app.layout = html.Div([
dcc.Graph(
id='life-exp-vs-gdp',
figure={
'data': [
go.Scatter(
x = performance_line[0],
y = performance_line[1],
mode = 'lines',
line = dict(
width=0.5
),
name = 'Fit'
),
go.Scatter(
x=df[df['continent'] == i]['gdp per capita'],
y=df[df['continent'] == i]['life expectancy'],
text=df[df['continent'] == i]['country'],
mode='markers',
opacity=0.7,
marker={
'size': 15,
'line': {'width': 0.5, 'color': 'white'}
},
name=i
) for i in df.continent.unique()
],
'layout': go.Layout(
xaxis={'type': 'log', 'title': 'GDP Per Capita'},
yaxis={'title': 'Life Expectancy'},
margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
legend={'x': 0, 'y': 1},
hovermode='closest'
)
}
)
])
if __name__ == '__main__':
app.run_server()
This code will not work because of the for loop after the scatter plot. I have tried encompassing it in () and [], but the JSON subroutine cannot handle generators and the [] stops the breaking but does not actually plot the scatter plot. How can i get this graph with the additional lowess regression?
It seems to me like a syntax problem, list comprehensions have the following format (forgive the simplicity):
[(something with i) for i in (iterable)]
while what you're trying looks like
[(unrelated item), (something with i) for i in (iterable)]
The following slight modification should work:
[(unrelated item)]+[(something with i) for i in (iterable)]
so the final code will be something like this.
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import statsmodels.api as sm
app = dash.Dash()
df = pd.read_csv(
'https://gist.githubusercontent.com/chriddyp/' +
'5d1ea79569ed194d432e56108a04d188/raw/' +
'a9f9e8076b837d541398e999dcbac2b2826a81f8/'+
'gdp-life-exp-2007.csv')
performance_line = pd.DataFrame(sm.nonparametric.lowess(df['life expectancy'], df['gdp per capita'], frac=0.75))
app.layout = html.Div([
dcc.Graph(
id='life-exp-vs-gdp',
figure={
'data': [
go.Scatter(
x = performance_line[0],
y = performance_line[1],
mode = 'lines',
line = dict(
width=0.5
),
name = 'Fit'
)
]+[
go.Scatter(
x=df[df['continent'] == i]['gdp per capita'],
y=df[df['continent'] == i]['life expectancy'],
text=df[df['continent'] == i]['country'],
mode='markers',
opacity=0.7,
marker={
'size': 15,
'line': {'width': 0.5, 'color': 'white'}
},
name=i
) for i in df.continent.unique()
],
'layout': go.Layout(
xaxis={'type': 'log', 'title': 'GDP Per Capita'},
yaxis={'title': 'Life Expectancy'},
margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
legend={'x': 0, 'y': 1},
hovermode='closest'
)
}
)
])
if __name__ == '__main__':
app.run_server()