Hi all,
TL;DR Pie chart not updating with callback and can’t assign an id to update a table.
Here is my code:
# import libraries
import pandas as pd
import plotly.express as px
import time
import json
import urllib
import urllib.request
# import dash libraries
import dash
import dash_core_components as dcc
# import dash bootstrap components
import dash_bootstrap_components as dbc
import dash_html_components as html
import dash_table
from dash.dependencies import Input, Output
from dash_bootstrap_templates import load_figure_template
#########################################
# data fetching and treatment starts here
# read JSON file from Json at emergencias.pt by Tomahock
url = "https://emergencias.pt/data"
response = urllib.request.urlopen(url).read()
jsonResponse = json.loads(response.decode('utf-8'))
# Create dataframe with pandas from json response
df = pd.json_normalize(jsonResponse['data'])
# Create new column that sums the values of men, vehicules, and planes/helicopters for each entry
df['total_meios'] = df['man'] + df['terrain']+df['aerial']
# Transform hour type to date/time format
df['hour'] =pd.to_datetime(df.hour)
# sort values by date/time
df.sort_values(by=['hour'])
# Create dataframe for table
df_table=df[["hour", "freguesia","naturezaName","status","total_meios"]]
########################################
# start plotting visualizations
# Create dataframe with the last 10 values
df_actual = df.tail(10)
# plot donut chart for the last 10 entries
fig_actual= px.pie(df_actual,names='district',values='total_meios',hole=0.7, color_discrete_sequence=px.colors.sequential.RdBu)
# fig_actual layout changes
fig_actual.update_layout(showlegend=False)
fig_actual.update_layout({
'plot_bgcolor': '#282b2f',
'paper_bgcolor': '#282b2f',
})
fig_actual.update_layout(
title="Recursos Alocados",
legend_title="Tipo de Ocorrência",
font=dict(
color="white",
size=12
)
)
fig_actual.update_traces(textposition='outside', textinfo='percent+label')
########################################
# create dashboard elements
table = dbc.Table.from_dataframe(df_table.tail(10), striped=True, bordered=True, hover=True)
# Get template for layout
load_figure_template("slate")
# design top navbar
VOSTPT_LOGO = "https://dash.vost.pt/wp-content/uploads/2020/11/cropped-VOSTPT_LOGO_PNG_TRANSP.png"
navbar = dbc.Navbar(
[
html.A(
# Use row and col to control vertical alignment of logo / brand
dbc.Row(
[
dbc.Col(html.Img(src=VOSTPT_LOGO, height="15px")),
dbc.Col(dbc.NavbarBrand("VOSTPT - DASHBOARD OPERACIONAL", className="ml-2")),
],
align="center",
no_gutters=True,
),
href="https://vost.pt",
),
],
color="dark",
dark=True,
)
# define Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.SLATE],title='VOST Portugal - DASHOARD',update_title=None,
meta_tags=[{'name': 'viewport',
'content': 'width=device-width, initial-scale=1.0, maximum-scale=1.2, minimum-scale=0.5,'}]
)
# start server
server = app.server
# app layout
app.layout = dbc.Container(
[
# set update intervals for the three graphs
dcc.Interval(
id='interval-component',
interval=30*1000, # in milliseconds
n_intervals=0
),
# insert navigation bar
navbar,
html.Hr(),
# create row
dbc.Row(
[
dbc.Col(dcc.Graph(id='graph_actual',figure=fig_actual,animate=True, className="h-100"),lg=6),
dbc.Col(table),
],
),
],
# set fluid to true to make the layout mobile ready
fluid=True,
)
@app.callback(
Output('graph_actual', 'figure'),
[Input('interval-component', "n_intervals")]
)
def UpdateFigActual(value):
global df_actual
url = "https://emergencias.pt/data"
response = urllib.request.urlopen(url).read()
jsonResponse = json.loads(response.decode('utf-8'))
df_new_actual = pd.json_normalize(jsonResponse['data'])
df_new_actual['DateAndTime'] = df_new_actual['date'].str.cat(df_new_actual['hour'],sep=" ")
df_new_actual.sort_values(by=['DateAndTime'])
df_new_actual['total_meios'] = df_new_actual['man'] + df_new_actual['terrain']+df_new_actual['aerial']
df_now_actual=df_new_actual.tail(10)
print(df_now_actual)
# Plot
fig_actual=px.pie(df_now_actual,names='district',values='district',hole=0.7, color_discrete_sequence=px.colors.sequential.Electric)
fig_actual.update_layout({
'plot_bgcolor': '#282b2f',
'paper_bgcolor': '#282b2f',
})
return fig_actual
# launch app
if __name__ == "__main__":
app.run_server(port=8052, debug=True)
What I have is a pie chart and a table. As you can see I choose, on purpose, two different color sequences, to test.
When I run the app it plots the graph the first time and on the terminal the dataframe updates.
However the chart doesn’t.
I’m also having troubles in creating a callback that updates the table with the last entries.
Anyone has any idea how to solve this? I’ve trying for the last hours but can’t come up with a solution for this.
Thank you in advance!
Note: This project is for a NGO, and not a commercial project. All code will be open source.