World Covid-19 Dashboard

#!pip install pandas
#!pip install plotly
#!pip install dash
#!pip install dash_bootstrap_components

import pandas as pd
pd.set_option('max_rows',20)
import plotly.express as px
import plotly.io as pio
pio.renderers.default = "browser"

import dash
from dash.dependencies import Input, Output
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc

Get Data

CONF_URL = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv'
DEAD_URL = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv'
RECV_URL = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv'

covid_conf_ts = pd.read_csv(CONF_URL)
covid_dead_ts = pd.read_csv(DEAD_URL)
covid_recv_ts = pd.read_csv(RECV_URL)

Data Processing

#get data in cleaned time series format for country
def process_data(data,cntry='US',window=3):
    conf_ts = data
    conf_ts_cntry = conf_ts[conf_ts['Country/Region']==cntry]
    final_dataset = conf_ts_cntry.T[4:].sum(axis='columns').diff().rolling(window=window).mean()[40:]
    df = pd.DataFrame(final_dataset,columns=['Total'])
    return df

#get overall wordlwide total for confirmed, recovered and dead cases
def get_overall_total(df):
    return df.iloc[:,-1].sum()

conf_overall_total = get_overall_total(covid_conf_ts)
dead_overall_total = get_overall_total(covid_dead_ts)
recv_overall_total = conf_overall_total - dead_overall_total
print('Overall Confirmed:',conf_overall_total)
print('Overall Dead:',dead_overall_total)
print('Overall Recovered:',recv_overall_total)
Overall Confirmed: 251420477
Overall Dead: 5072444
Overall Recovered: 246348033

#get total for confirmed, recovered and dead for country 
def get_cntry_total(df,cntry='US'):
    return df[df['Country/Region']==cntry].iloc[:,-1].sum()

cntry = 'US'
conf_cntry_total = get_cntry_total(covid_conf_ts,cntry)
dead_cntry_total = get_cntry_total(covid_dead_ts,cntry)
recv_cntry_total = conf_cntry_total - dead_cntry_total
print(f'{cntry} Confirmed:',conf_cntry_total)
print(f'{cntry} Dead:',dead_cntry_total)
print(f'{cntry} Recovered:',recv_cntry_total)
US Confirmed: 46789031
US Dead: 758916
US Recovered: 46030115

Generate Line Graph Using Plotly

def fig_world_trend(cntry='US',window=3):
    df = process_data(data=covid_conf_ts,cntry=cntry,window=window)
    df.head(10)
    if window==1:
        yaxis_title = "Daily Cases"
    else:
        yaxis_title = "Daily Cases ({}-day MA)".format(window)
    fig = px.line(df, y='Total', x=df.index, title='Daily confirmed cases trend for {}'.format(cntry),height=600,color_discrete_sequence =['maroon'])
    fig.update_layout(title_x=0.5,plot_bgcolor='#F2DFCE',paper_bgcolor='#F2DFCE',xaxis_title="Date",yaxis_title=yaxis_title)
    return fig

external_stylesheets = [dbc.themes.BOOTSTRAP]

Page Header and Form

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = 'World Covid-19 Dashboard'
colors = {
    'background': '#111111',
    'bodyColor':'#F2DFCE',
    'text': '#7FDBFF'
}
def get_page_heading_style():
    return {'backgroundColor': colors['background']}


def get_page_heading_title():
    return html.H1(children='World COVID-19 Dashboard',
                                        style={
                                        'textAlign': 'center',
                                        'color': colors['text']
                                    })

def get_page_heading_subtitle():
    return html.Div(children='Visualize Covid-19 data generated from sources all over the world.',
                                         style={
                                             'textAlign':'center',
                                             'color':colors['text']
                                         })
def generate_page_header():
    main_header =  dbc.Row(
                            [
                                dbc.Col(get_page_heading_title(),md=12)
                            ],
                            align="center",
                            style=get_page_heading_style()
                        )
    subtitle_header = dbc.Row(
                            [
                                dbc.Col(get_page_heading_subtitle(),md=12)
                            ],
                            align="center",
                            style=get_page_heading_style()
                        )
    header = (main_header,subtitle_header)
    return header

Select Country Dropdown

def get_country_list():
    return covid_conf_ts['Country/Region'].unique()

def create_dropdown_list(cntry_list):
    dropdown_list = []
    for cntry in sorted(cntry_list):
        tmp_dict = {'label':cntry,'value':cntry}
        dropdown_list.append(tmp_dict)
    return dropdown_list

def get_country_dropdown(id):
    return html.Div([
                        html.Label('Select Country'),
                        dcc.Dropdown(id='my-id'+str(id),
                            options=create_dropdown_list(get_country_list()),
                            value='US'
                        ),
                        html.Div(id='my-div'+str(id))
                    ])

Graph Container For Dash

def graph1():
    return dcc.Graph(id='graph1',figure=fig_world_trend('US'))

Generate CARDS for Overall Numbers

def generate_card_content(card_header,card_value,overall_value):
    card_head_style = {'textAlign':'center','fontSize':'150%'}
    card_body_style = {'textAlign':'center','fontSize':'200%'}
    card_header = dbc.CardHeader(card_header,style=card_head_style)
    card_body = dbc.CardBody(
        [
            html.H5(f"{int(card_value):,}", className="card-title",style=card_body_style),
            html.P(
                "Worlwide: {:,}".format(overall_value),
                className="card-text",style={'textAlign':'center'}
            ),
        ]
    )
    card = [card_header,card_body]
    return card

def generate_cards(cntry='US'):
    conf_cntry_total = get_cntry_total(covid_conf_ts,cntry)
    dead_cntry_total = get_cntry_total(covid_dead_ts,cntry)
    recv_cntry_total = conf_cntry_total - dead_cntry_total
    cards = html.Div(
        [
            dbc.Row(
                [
                    dbc.Col(dbc.Card(generate_card_content("Recovered",recv_cntry_total,recv_overall_total), color="success", inverse=True),md=dict(size=2,offset=3)),
                    dbc.Col(dbc.Card(generate_card_content("Confirmed",conf_cntry_total,conf_overall_total), color="warning", inverse=True),md=dict(size=2)),
                    dbc.Col(dbc.Card(generate_card_content("Dead",dead_cntry_total,dead_overall_total),color="dark", inverse=True),md=dict(size=2)),
                ],
                className="mb-4",
            ),
        ],id='card1'
    )
    return cards

DASH Slider for Moving Average Window

def get_slider():
    return html.Div([  
                        dcc.Slider(
                            id='my-slider',
                            min=1,
                            max=15,
                            step=None,
                            marks={
                                1: '1',
                                3: '3',
                                5: '5',
                                7: '1-Week',
                                14: 'Fortnight'
                            },
                            value=3,
                        ),
                        html.Div([html.Label('Select Moving Average Window')],id='my-div'+str(id),style={'textAlign':'center'})
                    ])

Generate APP layout

def generate_layout():
    page_header = generate_page_header()
    layout = dbc.Container(
        [
            page_header[0],
            page_header[1],
            html.Hr(),
            generate_cards(),
            html.Hr(),
            dbc.Row(
                [
                    dbc.Col(get_country_dropdown(id=1),md=dict(size=4,offset=4))                    
                ]
            
            ),
            dbc.Row(
                [                
                    
                    dbc.Col(graph1(),md=dict(size=6,offset=3))
        
                ],
                align="center",

            ),
            dbc.Row(
                [
                    dbc.Col(get_slider(),md=dict(size=4,offset=4))                    
                ]
            
            ),
        ],fluid=True,style={'backgroundColor': colors['bodyColor']}
    )
    return layout
app.layout = generate_layout()

Assign DASH Callbacks

@app.callback(
    [Output(component_id='graph1',component_property='figure'), #line chart
    Output(component_id='card1',component_property='children')], #overall card numbers
    [Input(component_id='my-id1',component_property='value'), #dropdown
     Input(component_id='my-slider',component_property='value')] #slider
)
def update_output_div(input_value1,input_value2):
    return fig_world_trend(input_value1,input_value2),generate_cards(input_value1)

RUN the app server

if __name__ == '__main__':
    app.run_server(debug=False)
Dash is running on http://127.0.0.1:8050/

 * Serving Flask app "__main__" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET /_favicon.ico?v=2.0.0 HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET /_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET /_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET /_dash-component-suites/dash/dcc/async-dropdown.js HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET /_dash-component-suites/dash/dcc/async-graph.js HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET /_dash-component-suites/dash/dcc/async-plotlyjs.js HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "GET /_dash-component-suites/dash/dcc/async-slider.js HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:01] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:11] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:26] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:06:52] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:07:11] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:07:38] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:07:53] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:08:00] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:09:00] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [11/Nov/2021 07:10:01] "POST /_dash-update-component HTTP/1.1" 200 -