How to update data from mySql for plotly dash - python

I’m trying to make a live updates from mySql database but graphs did not update with new data but Stop and Re-run script. I tried to find solutions or simple code but I couldn’t find it.
Below is my code:
import pandas as pd
import numpy as np
import plotly.express as px
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
from io import BytesIO
from wordcloud import WordCloud
import base64
import dash.dependencies as dd
import mysql.connector
db = mysql.connector.connect(
host="localhost",
user="root",
password="",
database="indeed_data_dump"
)
cur = db.cursor()
cur.execute("SELECT * FROM jobs")
data = pd.DataFrame(cur.fetchall())
db.close()
data.rename(columns = {1:'Url',2:'Job Link',3:'Title',4:'Company',5:'Rating',6:'Location',
7:'Posted',8:'Job Description',9:'Min Salary',10:'Max Salary'}, inplace = True)
data.to_dict()
data = data[data['Max Salary'].notnull()]
jobs_2 = data[['Title','Company','Rating','Location','Max Salary']]
jobs_2['Max Salary'] = jobs_2['Max Salary'].str.replace(',','')
jobs_2['Type'] = jobs_2['Max Salary'].str[-5:]
jobs_2['Type'] = jobs_2['Type'].str.replace(' ','')
jobs_2['Max Salary'] = jobs_2['Max Salary'].str.extract('(\d+)')
jobs_2 = jobs_2.dropna(subset=['Max Salary'])
jobs_2['Max Salary'] = jobs_2['Max Salary'].astype(int)
jobs_2['Max Salary'] = np.where((jobs_2['Type'] == "year"),(jobs_2['Max Salary']/12).round(decimals=0),jobs_2['Max Salary'])
jobs_2['Max Salary'] = np.where((jobs_2['Type'] == "week"),(jobs_2['Max Salary']*4).round(decimals=0),jobs_2['Max Salary'])
app = dash.Dash(__name__,external_stylesheets=[dbc.themes.LUX])
app.layout = html.Div([
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([html.H5('Average salary on each location',className='text-center'), #marks=mark_values
dcc.Graph(id='sal_location',figure={},style={'height':500,'width':'auto'}),
])
])
],width={'size':12,"offset":0,'order':1},style={'padding-left' : 25,'padding-right' : 25}),
]),
html.Hr(),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([html.H5('Top 10 Job',className='text-center'), #marks=mark_values
dcc.Graph(id='sal_top10',figure={},style={'height':600,'width':'auto'}),
])
])
],width={'size':6,"offset":0,'order':1},style={'padding-left' : 25}),
dbc.Col([
dbc.Card([
dbc.CardBody([html.H5('Average salary on star',className='text-center'), #marks=mark_values
dcc.Graph(id='sal_star',figure={},style={'height':600,'width':'auto'}),
])
])
],width={'size':6,"offset":0,'order':1},style={'padding-right' : 25}),
]),
html.Hr(),
dbc.Row([
dbc.Col([html.H5('Drop Down',className='text-center'),
dcc.Dropdown(id='location_cd_2',placeholder="Please select location",
options=[{'label':x,'value':x} for x in data.sort_values('Location')['Location'].unique()],
value='Select',
multi=False,
disabled=False,
clearable=True,
searchable=True),
],width={'size':6,"offset":0,'order':1},style={'padding-left' : 25}),
]),
html.Hr(),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([html.H5('Job on each location',className='text-center'), #marks=mark_values
dcc.Graph(id='job_location_2',figure={},style={'height':600,'width':'auto'}),
])
])
],width={'size':12,"offset":0,'order':1},style={'padding-left' : 25,'padding-right' : 25}),
]),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([html.H5('Word Cloud',className='text-center'),
html.Img(id="image_wc"),
])
])
],width={'size':12,"offset":0,'order':1},style={'padding-left' : 25,'padding-right' : 25},className='text-center'),
]),
dcc.Interval(id='update', n_intervals = 0, interval=1000*5)
])
#app.callback(
Output('sal_location', 'figure'),
[Input('update', 'n_intervals')])
def update_graph(jobs_location):
global jobs
jobs = jobs_2.copy()
jobs_location = pd.pivot_table(jobs,values=['Max Salary',],index=['Location'],aggfunc=np.mean)
jobs_location = jobs_location.reset_index()
# Fig 1
fig_1 = go.Figure(data=[
go.Bar(x=jobs_location['Location'],
y=jobs_location['Max Salary'].round(decimals=2),
width=0.45,
text = jobs_location['Max Salary'].round(decimals=2),
textposition='inside',
marker_color='indianred')])
fig_1.update_layout(barmode='stack')
fig_1.update_traces(texttemplate='%{text:,}')
fig_1.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig_1.update_yaxes(showline=False,showgrid=False,dtick=5000,exponentformat="none",separatethousands=True)
return fig_1
#app.callback(
Output('sal_top10', 'figure'),
[Input('update', 'n_intervals')])
def update_graph_2(top_10):
global job_cloud
jobs['Rating'].fillna(0,inplace=True)
jobs_title = pd.pivot_table(jobs,values=['Max Salary',],index=['Title'],aggfunc=np.mean)
jobs_title = jobs_title.reset_index()
top_10 = jobs_title.sort_values(['Max Salary'], ascending=[False]).head(10)
top_10 = top_10.sort_values(['Max Salary'], ascending=[True])
job_cloud = jobs.groupby(["Title"])["Title"].count().reset_index(name="count")
# Fig 3
fig_3 = px.bar(top_10, x="Max Salary", y="Title", orientation='h')
fig_3.update_traces(marker_color='#E8788C')
fig_3.update_layout(plot_bgcolor='white',xaxis_title='',yaxis_title='')
fig_3.update_yaxes(showline=False,showgrid=False,exponentformat="none",separatethousands=True)
fig_3.update_xaxes(showline=False,showgrid=False,exponentformat="none",separatethousands=True)
return fig_3
#app.callback(
Output('sal_star', 'figure'),
[Input('update', 'n_intervals')])
def update_graph_3(jobs_rating):
jobs_rating = pd.pivot_table(jobs,values=['Max Salary',],index=['Rating'],aggfunc=np.mean)
jobs_rating = jobs_rating.reset_index()
fig_2 = go.Figure(data=[
go.Bar(x=jobs_rating['Rating'],
y=jobs_rating['Max Salary'].round(decimals=2),
width=0.45,
text = jobs_rating['Max Salary'].round(decimals=2),
textposition='inside',
marker_color='lightsalmon')])
fig_2.update_layout(barmode='stack')
fig_2.update_traces(texttemplate='%{text:,}')
fig_2.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig_2.update_yaxes(showline=False,showgrid=False,dtick=5000,exponentformat="none",separatethousands=True)
fig_2.update_xaxes(type='category')
return fig_2
#app.callback(Output('job_location_2', 'figure'),
[Input('location_cd_2', 'value'),
Input('update', 'n_intervals')])
def build_graph(location_code,dff_2):
if not location_code or 'Select' in location_code:
dff_2 = pd.pivot_table(jobs,values=['Max Salary',],index=['Location','Title'],aggfunc=np.mean).reset_index()
dff_2 = dff_2[(dff_2['Location']=='Kuala Lumpur')]
else:
dff_2 = pd.pivot_table(jobs,values=['Max Salary',],index=['Location','Title'],aggfunc=np.mean).reset_index()
dff_2 = dff_2[(dff_2['Location'] == location_code)]
fig_4 = go.Figure(data=[
go.Bar(x=dff_2['Title'],
y=dff_2['Max Salary'].round(decimals=2),
width=0.45,
text = dff_2['Max Salary'].round(decimals=2),
textposition='inside',
marker_color='lightsalmon')])
fig_4.update_layout(barmode='stack')
fig_4.update_traces(texttemplate='%{text:,}')
fig_4.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig_4.update_yaxes(showline=False,showgrid=False,dtick=20000,exponentformat="none",separatethousands=True)
fig_4.update_xaxes(type='category')
return fig_4
def plot_wordcloud(data):
d = {a: x for a, x in data.values}
wc = WordCloud(background_color='white', width=1080, height=360)
wc.fit_words(d)
return wc.to_image()
#app.callback(dd.Output('image_wc', 'src'), [dd.Input('image_wc', 'id')])
def make_image(b):
img = BytesIO()
plot_wordcloud(data=job_cloud).save(img, format='PNG')
return 'data:image/png;base64,{}'.format(base64.b64encode(img.getvalue()).decode())
if __name__ == "__main__":
app.run_server(debug=False,port=1215)
This code worked good with csv files but didn't update data from mySql.
What should I change for my code or could you give me a sample code? Thank you.

Related

Not able to render charts using plotly and python dash

I created a dash app to render some real time charts using plotly.objs. All the data is being created in the database so it's not like the charts are empty.
The page where the dash app renders the charts is blank. It does not show any errors even in debug mode.The complete code is given below:
import dash
from dash import html,dcc
from dash.dependencies import Output, Input
import plotly
import random
import plotly.graph_objs as go
# from collections import deque
import datetime
from plotly.subplots import make_subplots
from pymongo import MongoClient
# from time import ctime
import time
from math import ceil
from configparser import ConfigParser
from waitress import serve
todays_date = str(datetime.datetime.today().date())
config = ConfigParser()
configfile = 'config.ini'
config.read(configfile)
try:
host = config['server']['host']
port = int(config['server']['port'])
mhost = config['mongo']['host']
mport = int(config['mongo']['port'])
muser = config['mongo']['user']
mpass = config['mongo']['pass']
except Exception as e:
print(f'Error in taking config values: {e}')
app = dash.Dash(__name__)
conn = MongoClient(host=mhost,port=mport,username=muser,password=mpass)
db = conn['GraphData']
collec = db[todays_date]
app = dash.Dash(__name__,title='IV Graphs',update_title='Plotting...')
app.layout = html.Div(
[
html.Div(children=html.Div(id='live-graph'), className='row'),
dcc.Interval(
id = 'graph-update',
interval = 5000,
n_intervals = 0
),
]
)
#app.callback(
Output('live-graph', 'children'),
[ Input('graph-update', 'n_intervals') ]
)
def update_graph_scatter(n):
colLimit = 2
plotData = list(collec.find())#{'$and':[{'title':{'$ne':'AD BN'}},{'title':{'$ne':'AD N'}}]}))
# print(plotData)
titleList = []
reqOrder = ['AD N','AD BN','NIFTY CALL WEEKLY IV', 'BANKNIFTY CALL WEEKLY IV',
'NIFTY PUT WEEKLY IV', 'BANKNIFTY PUT WEEKLY IV',
'NIFTY CALL MONTHLY IV', 'BANKNIFTY CALL MONTHLY IV',
'NIFTY PUT MONTHLY IV', 'BANKNIFTY PUT MONTHLY IV', 'PCR CURRENT N',
'PCR CURRENT BN','PCR NEXT N','PCR NEXT BN']
for titleData in reqOrder:
for dbData in plotData:
if dbData['title'] == titleData:
if titleData == 'AD BN' or titleData == 'AD N':
titleList.append(f"{dbData['title']}: {dbData['ratio']} UP: {dbData['up']} DOWN: {dbData['down']}")
break
else:
titleList.append(dbData['title'] + ": "+ str(round(float(dbData['yaxis'][-1]),2)))
print(titleList)
fig = make_subplots(rows=ceil(len(reqOrder)/colLimit), cols=colLimit,
subplot_titles=tuple(titleList),
)
colNum = 1
rowNum = 1
graphs = []
LAYOUT = {
'plot_bgcolor': 'white',
'paper_bgcolor': 'white'
}
fig['layout'].update(LAYOUT)
for algo in reqOrder:
for dbData in plotData:
if dbData['title'] == algo:
xData = convertTimeStamps(dbData['xaxis'])
yData = convertToFloat(dbData['yaxis'])
if colNum>colLimit:
colNum = 1
rowNum+=1
# print([0 for i in plotData[dbData].keys()])
fig.add_trace(
go.Scatter(mode ="lines",
x=xData, y=yData),
row=rowNum, col=colNum
)
if dbData['title'] == 'AD BN' or dbData['title'] == 'AD N':
# fig.add_hline(y=0)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[0 for i in xData]),
row=rowNum, col=colNum
)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[0 for i in xData]),
row=rowNum, col=colNum
)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[2 for i in xData]),
row=rowNum, col=colNum
)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[0.5 for i in xData]),
row=rowNum, col=colNum
)
colNum+=1
# break
fig.update_layout(
autosize = True
)
print(fig)
graphs.append(html.Div(style={
'display': 'flex',
'flex-flow': 'column',
'background-color': 'green',
'height': '200vh',
'width': '100%'
},children = [ dcc.Graph(
id='basic-interactions',
figure=fig,
style={'height': '100%'}
)]))
return graphs
def convertTimeStamps(epochList):
ans = []
for timeStamp in epochList:
ans.append(datetime.datetime.fromtimestamp(timeStamp))
return ans
def convertToFloat(data):
ans = []
for p in data:
ans.append(float(p))
return ans
if __name__ == '__main__':
app.run_server(host=host, port=port,debug = False)
I tried to restart the page and even the system. What is wrong here?

Plot bar chart with separate color legend - dash Plotly

I'm trying to plot certain values using dash as a bar chart but use a separate column to map the colors. Using below, I'm plotting dates as a bar-chart that corresponds to a drop down bar.
Is it possible to keep the dates as the x-axis but use DOW (day of the week) as a discrete color map? I'll attach the current output below. The dates get plotted but there are a few issues.
The string formatting for each date in the dropdown isn't in date time
The color map isn't sequenced to the day of the week
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
from datetime import datetime as dt
df = pd.DataFrame({
'Type': ['A','B','B','B','C','C','D','E','E','E','E','F','F','F'],
})
N = 30
df = pd.concat([df] * N, ignore_index=True)
df['TIMESTAMP'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df))
df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'], dayfirst = True).sort_values()
df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
df['DATE'] = pd.to_datetime(df['DATE'])
df = df.sort_values(by = 'DATE')
df['DOW'] = df['DATE'].dt.weekday
df = df.sort_values('DOW').reset_index(drop=True)
df['DOW'] = df['DATE'].dt.day_name()
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filter_box = html.Div(children=[
html.Div(children=[
html.Label('Day of the week:', style={'paddingTop': '2rem'}),
dcc.Dropdown(
id='DATE',
options=[
{'label': x, 'value': x} for x in df['DATE'].unique()
],
value=df['DATE'].unique(),
multi=True
),
], className="four columns",
style={'padding':'2rem', 'margin':'1rem'} )
])
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(filter_box, className="bg-secondary h-100"), width=2),
dbc.Col([
dbc.Row([
dbc.Col(dcc.Graph(id = 'date-bar-chart'),
),
]),
], width=5),
])
], fluid=True)
#app.callback(
Output('date-bar-chart', 'figure'),
[Input("DATE", "value"),
])
def date_chart(date):
dff = df[df['DATE'].isin(date)]
count = dff['DATE'].value_counts()
data = px.bar(x = count.index,
y = count.values,
#color = dff['DOW'],
)
layout = go.Layout(title = 'Date')
fig = go.Figure(data = data, layout = layout)
return fig
if __name__ == '__main__':
app.run_server(debug=True, port = 8051)
Not sure why do you want to use DATE as Dropdown but I think you should change it to string and then pass it to dcc.Dropdown. Used the previous way to add color_discrete_map I think you can revise your code as below:
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
from datetime import datetime as dt
from dash.exceptions import PreventUpdate
df = pd.DataFrame({
'Type': ['A','B','B','B','C','C','D','E','E','E','E','F','F','F'],
})
N = 30
df = pd.concat([df] * N, ignore_index=True)
df['TIMESTAMP'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df))
df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'], dayfirst = True).sort_values()
df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
df['DATE'] = pd.to_datetime(df['DATE'],format='%Y-%m-%d')
df = df.sort_values(by = 'DATE')
df['DOW'] = df['DATE'].dt.weekday
df = df.sort_values('DOW').reset_index(drop=True)
df['DOW'] = df['DATE'].dt.day_name()
df['DATE'] = df['DATE'].astype(str)
df['Color'] = df['DOW'].map(dict(zip(df['DOW'].unique(),
px.colors.qualitative.Plotly[:len(df['DOW'].unique())])))
Color = df['Color'].unique()
Category = df['DOW'].unique()
Color = df['Color'].unique()
Category = df['DOW'].unique()
cats = dict(zip(Category,Color))
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filter_box = html.Div(children=[
html.Div(children=[
html.Label('Day of the week:', style={'paddingTop': '2rem'}),
dcc.Dropdown(
id='DATE',
options=[
{'label': x, 'value': x} for x in df['DATE'].unique()
],
value=df['DATE'].unique(),
multi=True
),
], className="four columns",
style={'padding':'2rem', 'margin':'1rem'} )
])
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(filter_box, className="bg-secondary h-100"), width=2),
dbc.Col([
dbc.Row([
dbc.Col(dcc.Graph(id = 'date-bar-chart'),
),
]),
], width=5),
])
], fluid=True)
#app.callback(
Output('date-bar-chart', 'figure'),
[Input("DATE", "value"),
])
def date_chart(date):
if date:
dff = df[df['DATE'].isin(date)]
count = dff.groupby(['DATE',"DOW"])['DATE'].count().reset_index(name='counts')
data = px.bar(x = count['DATE'],
y = count['counts'],
color = count['DOW'],
color_discrete_map = cats,
)
layout = go.Layout(title = 'Date')
fig = go.Figure(data = data, layout = layout)
return fig
else:
raise PreventUpdate
if __name__ == '__main__':
app.run_server(debug=False, port = 8051)
I used groupby in callback to return new dataframe and then use it to make graph. Hope this help.

Displaying an image with dcc.Graph in Plotly-Dash

I am trying to display an image with with dcc.Graph component in Plotly-Dash so I get its nice toolbars and built-in UI. However I am getting a bunch of errors. This is what my procedure is:
Upload JPG image.
Load image using np.array(Image.open(..)).
Convert to figure with px.imshow().
Pass this through dcc.Graph component and try to display it on page.
Below is my code:
import datetime
import dash
from dash.dependencies import Input, Output, State
from dash import dcc
from dash import html
import numpy as np
from PIL import Image
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div(
children=[
dcc.Upload(
id='upload-image',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
# Allow multiple files to be uploaded
multiple=True)]),
html.Div(
children=[
html.Div(id='output-image-upload'),
])
])
def parse_contents(contents, filename, date):
img = np.array(Image.open(contents))
fig = px.imshow(img)
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dcc.Graph(figure=fig)
])
#app.callback(Output('output-image-upload', 'children'),
Input('upload-image', 'contents'),
State('upload-image', 'filename'),
State('upload-image', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
if __name__ == '__main__':
app.run_server(debug=True)
I get these errors below:
Callback error updating output-image-upload.children
Traceback (most recent call last):
File "C:\Users\...\test.py", line 48, in update_output
children = [
File "C:\Users\...\test.py", line 49, in <listcomp>
parse_contents(c, n, d) for c, n, d in
File "C:\Users\...\test.py", line 34, in parse_contents
img = np.array(Image.open(contents))
File "C:\Users\...\AppData\Local\Programs\Python\Python38\Lib\site-packages\PIL\Image.py", line 2904, in open
fp = builtins.open(filename, "rb")
FileNotFoundError: [Errno 2] No such file or directory: 'data:image/jpeg;base64,/9j/2wBDAAYEBQY...
As explained in this answer you need to remove data:image/png;base64, from the image string. If you update your parse_contents function as follows your app should work:
def parse_contents(contents, filename, date):
# Remove 'data:image/png;base64' from the image string,
# see https://stackoverflow.com/a/26079673/11989081
data = contents.replace('data:image/png;base64,', '')
img = Image.open(io.BytesIO(base64.b64decode(data)))
# Convert the image string to numpy array and create a
# Plotly figure, see https://plotly.com/python/imshow/
fig = px.imshow(np.array(img))
# Hide the axes and the tooltips
fig.update_layout(
plot_bgcolor='white',
paper_bgcolor='white',
margin=dict(t=20, b=0, l=0, r=0),
xaxis=dict(
showgrid=False,
showticklabels=False,
linewidth=0
),
yaxis=dict(
showgrid=False,
showticklabels=False,
linewidth=0
),
hovermode=False
)
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dcc.Graph(
figure=fig,
config={'displayModeBar': True} # Always display the modebar
)
])
Full code:
import io
import base64
import datetime
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import numpy as np
import plotly.express as px
from PIL import Image
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div(
children=[
dcc.Upload(
id='upload-image',
children=html.Div(['Drag and Drop or ', html.A('Select Files')]),
multiple=True
)
]
),
html.Div(
children=[
html.Div(id='output-image-upload'),
]
)
])
def parse_contents(contents, filename, date):
# Remove 'data:image/png;base64' from the image string,
# see https://stackoverflow.com/a/26079673/11989081
data = contents.replace('data:image/png;base64,', '')
img = Image.open(io.BytesIO(base64.b64decode(data)))
# Convert the image string to numpy array and create a
# Plotly figure, see https://plotly.com/python/imshow/
fig = px.imshow(np.array(img))
# Hide the axes and the tooltips
fig.update_layout(
plot_bgcolor='white',
paper_bgcolor='white',
margin=dict(t=20, b=0, l=0, r=0),
xaxis=dict(
showgrid=False,
showticklabels=False,
linewidth=0
),
yaxis=dict(
showgrid=False,
showticklabels=False,
linewidth=0
),
hovermode=False
)
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dcc.Graph(
figure=fig,
config={'displayModeBar': True} # Always display the modebar
)
])
#app.callback(
Output('output-image-upload', 'children'),
[Input('upload-image', 'contents')],
[State('upload-image', 'filename'),
State('upload-image', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)
]
return children
if __name__ == '__main__':
app.run_server(debug=True, host='127.0.0.1')

Graph is not being returned by Plotly Dash Callback

I'm doing some GIS analysis and got a bit flustered.
I need to create a interactive plotly dash app, where you have two multi dropdown dash core components that update values on a px.scatter_mapbox map. The DataFrame has the following "Filters"/Fields I need in the dropdowns: Race/Ethnicity and City. I'm stuck at this point:
Click on the Race Drop down (Multi) (works)
City Options are appropriately filled (works)
Map won't update-- just returns what you see below.
Here is my code:
import dash.dependencies
import plotly.express as px
import pandas as pd
from jupyter_dash import JupyterDash
import dash_core_components as dcc
from dash import html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
px.set_mapbox_access_token(mapbox_access_token)
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = JupyterDash(__name__, external_stylesheets=external_stylesheets)
re_indicators = df["RE"].unique()
city_indicators = df["CITY"].unique()
app.layout = html.Div([
html.Div(children=[
html.Label('Race & Ethnicity'),
dcc.Dropdown( id = "re",
options=[{'label': i, 'value': i} for i in re_indicators],
value = ["White"],
multi = True
),
html.Label('City'),
dcc.Dropdown( id = "city",
options=[],
value = [],
multi = True
),
html.Div([
dcc.Graph(
id='my_map',
figure = {})
])
])])
#app.callback(
dash.dependencies.Output('city', 'options'),
dash.dependencies.Input('re', 'value')
)
def re_picker(choose_re):
if len(choose_re) > 0:
dff = df[df.RE.isin(choose_re)]
return [{'label': i, 'value': i} for i in (dff.CITY.unique())]
#app.callback(
dash.dependencies.Output('city', 'value'),
dash.dependencies.Input('city', 'options')
)
def set_city_value(available_options):
return [x['value'] for x in available_options]
#app.callback(
dash.dependencies.Output('my_map', 'figure'),
[dash.dependencies.Input('re', 'value'),
dash.dependencies.Input('city', 'value')]
)
def update_figure(selected_re, selected_city):
if len(selected_re) == 0:
return print("nope")
else:
df_filtered = dff[(dff['CITY'] == selected_city)]
fig = px.scatter_mapbox(df_filtered,
lat="Latitude",
lon="Longitude",
zoom=1)
return fig
# Run app and display result inline in the notebook
if __name__ == '__main__':
app.run_server(host = "127.0.0.1", port = "8888", mode= "inline", debug = False)
Ouput Photo
you have not provided any data, have generated some sample data
there are a number issues with your code. All actually generate obvious exceptions
scoping, dff is note scoped across all callbacks however you are assuming it is. Fixes are to only have df as global scope
list equality makes no sense. use isin()
better practice is to use raise dash.exceptions.PreventUpdate if conditions for callback are not met
solution
import dash.dependencies
import plotly.express as px
import pandas as pd
from jupyter_dash import JupyterDash
import dash_core_components as dcc
from dash import html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
# px.set_mapbox_access_token(mapbox_access_token)
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = JupyterDash(__name__, external_stylesheets=external_stylesheets)
re_indicators = df["RE"].unique()
city_indicators = df["CITY"].unique()
app.layout = html.Div(
[
html.Div(
children=[
html.Label("Race & Ethnicity"),
dcc.Dropdown(
id="re",
options=[{"label": i, "value": i} for i in re_indicators],
value=["White"],
multi=True,
),
html.Label("City"),
dcc.Dropdown(id="city", options=[], value=[], multi=True),
html.Div([dcc.Graph(id="my_map", figure={})]),
]
)
]
)
#app.callback(
dash.dependencies.Output("city", "options"), dash.dependencies.Input("re", "value")
)
def re_picker(choose_re):
if len(choose_re) > 0:
dff = df[df.RE.isin(choose_re)]
else:
raise dash.exceptions.PreventUpdate
return [{"label": i, "value": i} for i in (dff.CITY.unique())]
#app.callback(
dash.dependencies.Output("city", "value"),
dash.dependencies.Input("city", "options"),
)
def set_city_value(available_options):
return [x["value"] for x in available_options]
#app.callback(
dash.dependencies.Output("my_map", "figure"),
[dash.dependencies.Input("re", "value"), dash.dependencies.Input("city", "value")],
)
def update_figure(selected_re, selected_city):
if not selected_re or not selected_city or len(selected_re)==0 or len(selected_city)==0:
raise dash.exceptions.PreventUpdate
# df_filtered = dff[(dff['CITY'] == selected_city)] # this is out of scope!!!
df_filtered = df.loc[df["CITY"].isin(selected_city) & df["RE"].isin(selected_re)]
fig = px.scatter_mapbox(df_filtered, lat="Latitude", lon="Longitude", zoom=1).update_layout(mapbox={"style":"carto-positron"})
return fig
# Run app and display result inline in the notebook
if __name__ == "__main__":
app.run_server(host="127.0.0.1", port="8888", mode="inline", debug=False)
data
import io
import pandas as pd
df = pd.read_csv(io.StringIO("""RE,Longitude,Latitude,CITY
Black,-120.99774156574261,37.559165406261,Stanislaus
Pacific,-120.65111562736087,38.446389516422855,Amador
Pacific,-119.81550247702623,36.07536100517565,Kings
Black,-121.95120685287338,37.92342159137978,Contra Costa
Native,-118.26100262413676,34.197992401614535,Los Angeles
Asian,-120.7249673888429,41.58984787469562,Modoc
White,-121.95120685287338,37.92342159137978,Contra Costa
Hispanic,-123.9578138104391,41.74495737627584,Del Norte
Black,-122.39220680431815,39.59840477506362,Glenn
Pacific,-122.04052155027398,40.7637665910163,Shasta
Black,-120.71766862423333,37.19185694553567,Merced
Native,-121.69484223375345,39.03452277403378,Sutter
Black,-115.9938588669452,33.743676039870444,Riverside
Black,-119.90551726806129,37.58152187924647,Mariposa
Pacific,-117.41078970333236,36.51112681410214,Inyo
Black,-119.76264585146096,37.218035870388235,Madera
Pacific,-123.43155392039253,39.433623844726505,Mendocino
Black,-121.34428014540734,38.4493728777556,Sacramento
White,-120.7249673888429,41.58984787469562,Modoc
Pacific,-119.64932124370894,36.758179506828185,Fresno
White,-119.81550247702623,36.07536100517565,Kings
Native,-121.91788591709779,37.65054956250571,Alameda
Asian,-121.07499558470187,36.6057059207284,San Benito
Native,-120.52464692805631,38.778737966889466,El Dorado
Pacific,-120.55413218695809,38.204606401638536,Calaveras
Hispanic,-116.17845588321354,34.84143467938159,San Bernardino
Black,-122.23388486629841,40.12573617303074,Tehama
White,-121.90162044594241,38.68664649354098,Yolo
Native,-120.45219691432906,35.38741552944272,San Luis Obispo
Pacific,-119.82065303166894,38.59725063024503,Alpine"""))

Dash graph does not display

I am trying to make a graph with Dash. When I copy the examples in Plotly it works fine, but when I change some variables with my values and run it then all the elements appear except for the graph.
This is the code:
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='graph-with-slider'),
dcc.Slider(
id='year-slider',
min=subset_date['Year'].unique().min(),
max=subset_date['Year'].unique().max(),
value=subset_date['Year'].unique().min(),
step=None
)
])
#app.callback(
Output('graph-with-slider', 'figure'),
[Input('year-slider', 'value')])
def update_figure(selected_year):
return {
'data': go.Scatter(x=subset_date.index,
y=subset_date['Value'],
mode='lines'),
'layout': go.Layout(
title='My Title'
)
}
if __name__=='__main__':
app.run_server()
What am I doing wrong?
Here is a simple app layout:
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
# Step 1. Launch the application
app = dash.Dash()
# Step 2. Import the dataset
# Scimago Journal & Country Rank
# from www.scimagojr.com
st = {'Date': ['2008-01-01', '2009-01-01', '2010-01-01', '2011-01-01', '2012-01-01', '2013-01-01', '2014-01-01', '2015-01-01', '2016-01-01','2017-01-01', '2018-01-01'],
# 'Turkey': [26526, 30839, 33325, 34926, 36766, 40302, 41400, 44529, 47138, 44584,45582],
'Iran': [20006, 24509, 30013, 39682, 41513, 42252, 44923, 45013, 52538, 56029, 60268]
}
st = pd.DataFrame(st)
# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2008-01-01', '2009-01-01', '2010-01-01', '2011-01-01', '2012-01-01', '2013-01-01', '2014-01-01', '2015-01-01', '2016-01-01','2017-01-01', '2018-01-01']
# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['Iran'],
name = 'Iran',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Scimago Journal & Country Rank (Iran)',
hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)
# Step 4. Create a Dash layout
app.layout = html.Div([
# adding a plot
dcc.Graph(id = 'plot', figure = fig),
# range slider
dcc.RangeSlider(id = 'slider',
marks = {i : dates[i] for i in range(0, 11)},
min = 0,
max = 10,
value = [1, 7])
])
# Step 5. Add callback functions
#app.callback(Output('plot', 'figure'),
[
Input('slider', 'value')])
def update_figure( input2):
# filtering the data
st2 = st[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
# updating the plot
trace_1 = go.Scatter(x = st2.Date, y = st2['Iran'],
name = 'Iran',
# mode = 'markers'
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
fig = go.Figure(data = [trace_1], layout = layout)
return fig
# Step 6. Add the server clause
if __name__ == '__main__':
app.run_server(debug = False)

Categories

Resources