Hello,
I’m having a really weird problem that I’m not sure how to solve. I’m building a COVID19 dashboard in Plotly Dash and I want to report the number of cumulative cases and cumulative deaths globally by date. I have two cards that display these numbers and I want them to update based on the date selected in my slider. Here’s an example of the code:
#Import packages
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
import time
who_data = pd.read_csv("https://covid19.who.int/WHO-COVID-19-global-data.csv")
who_data.rename(columns={'New_cases': 'New Cases', 'Cumulative_cases': 'Cumulative Cases', 'New_deaths': 'New Deaths','Cumulative_deaths': 'Cumulative Deaths'}, inplace=True)
who_data['Date_reported_string'] = who_data['Date_reported'].copy()
who_data['Date_reported'] = who_data['Date_reported'].str.replace('-', '').astype(int)
card1_body = dbc.CardBody([html.H4("Card title", className="card-title",id="card_num1"),
html.P("Cumulative Cases for Date", className="card-text",id="card_text1")
],
style={'display': 'inline-block',
'text-align': 'center',
'color':'white',
'background-color': 'rgba(37, 150, 190)'})
card2_body = dbc.CardBody([html.H4("Card title", className="card-title",id="card_num2"),
html.P("Cumulative Deaths for Date", className="card-text",id="card_text2")
],
style={'display': 'inline-block',
'text-align': 'center',
'color':'white',
'background-color': 'rgba(37, 150, 190)'})
card1 = dbc.Card(card1_body,outline=True)
card2 = dbc.Card(card2_body,outline=True)
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
dcc.Tabs([
dcc.Tab(label='Spread',
children=[
html.Div([
dcc.Slider(id='slider',
min = who_data['Date_reported'].min(),
max = who_data['Date_reported'].max(),
value = who_data['Date_reported'].min()#,
# marks={each : {"label": who_data['Date_reported_string'],
# "style": {"transform": "rotate(45deg)"}}
# for each, who_data['Date_reported_string']
# in enumerate(who_data['Date_reported'])},
),
dbc.Row(id="card_row",children=[dbc.Col(card1),
dbc.Col(card2)
])
])
])
])
])
@app.callback(
Output('card_row','children'),
Input('slider','value')
)
def update_cards(date_select):
date_df = who_data[who_data['Date_reported']<=date_select]
tot_cases = f"{date_df['New Cases'].sum():,.0f}"
tot_deaths = f"{date_df['New Deaths'].sum():,.0f}"
card1 = dbc.Card([
dbc.CardBody([
html.H4(tot_cases, className="card-title"),
html.P(f"Cumulative Cases on {date_select}")
])
],
style={'display': 'inline-block',
'width': '50%',
'text-align': 'center',
'background-color': 'rgba(37, 150, 190)',
'color':'white',
'fontWeight': 'bold',
'fontSize':20},
outline=True)
card2 = dbc.Card([
dbc.CardBody([
html.H4(tot_deaths, className="card-title"),
html.P(f"Cumulative Deaths on {date_select}")
])
],
style={'display': 'inline-block',
'width': '50%',
'text-align': 'center',
'background-color': 'rgba(37, 150, 190)',
'color':'white',
'fontWeight': 'bold',
'fontSize':20},
outline=True)
return (card1, card2)
app.run_server(host='0.0.0.0',port='8050')
If you try using the slider, it will filter the dataset appropriately, but since I converted the date to an integer value, the increments for which slider step through are not the same as moving through each unique value in who_data[‘Date_reported’]. Ideally, I would like to have the slider read dates as follows, “20200330, 20200331, 20200401,…” But instead, I’m getting, “20200330, 20200331, 20200332,…”. It will literally step the date value up by one. Not sure how this happened or even how to fix it - I’m not getting any errors.
Does anyone know how to fix this? Any help would be appreciated!