Candidate number: 31 Home Exam BAN438
import pandas as pd
import plotly.express as px
from pandas_datareader import wb
import pandas_datareader.data as web
from datetime import datetime, timedelta
from jupyter_dash import JupyterDash
from dash import dcc, html
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import load_figure_template
from dash.dependencies import Input, Output
dbc_css = 'https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap-templates@V1.0.2/dbc.min.css'
load_figure_template('bootstrap')
This notebook develops a dash
application that allows users to explore how the COVID-19 situation has developed around the world
The notebook first compiles data on the development of COVID-19 cases, deaths and vaccinations by extracting data from Ourworldindata
by using pandas-datareader
. It then uses the data to create a dashboard with different visualizations that allow users to explore global COVID-19 cases, deaths and vaccinations.
Read the data in Python from https://covid.ourworldindata.org/data/owid-covid-data.csv
#read the csv file
covid19_df = pd.read_csv("https://covid.ourworldindata.org/data/owid-covid-data.csv")
# import the necessary columns
covid19_df = covid19_df[['iso_code', 'location', 'continent', 'date', 'new_cases', 'total_cases', 'total_cases_per_million',
'new_deaths', 'total_deaths', 'total_deaths_per_million', 'new_vaccinations', 'people_fully_vaccinated',
'total_vaccinations_per_hundred', 'people_vaccinated_per_hundred']].copy()
covid19_df
#remove continents
covid19_df = covid19_df[~(covid19_df.location.isin(['Asia', 'Europe', 'European Union', 'North America', 'South America', 'Africa', 'Upper middle income', 'World' ]))].reset_index()
This is a static (i.e. non-interactive) feature that simply states the accumulated number of deaths, cases and people that are fully vaccinated in the world up to the current date.
# compute total deaths
total_deaths = covid19_df['total_deaths'].sum().astype(int)
total_cases = covid19_df['total_cases'].sum().astype(int)
people_fully_vaccinated = covid19_df['people_fully_vaccinated'].sum().astype(int)
#format with comma
total_deaths = "{:,}".format(total_deaths)
total_cases = "{:,}".format(total_cases)
people_fully_vaccinated = "{:,}".format(people_fully_vaccinated)
card1 = dbc.Card( #create a first card component
children = [
html.P('Static feature states the accumulated number of COVID 19', className = 'card-text'),
# 1st row with number
dbc.Row([
dbc.Col(html.H2(total_deaths), width = 4),
dbc.Col(html.H2(total_cases), width = 4),
dbc.Col(html.H2(people_fully_vaccinated), width = 4)]),
# 2nd row with label
dbc.Row([
dbc.Col(html.H6('Total deaths'), width = 4),
dbc.Col(html.H6('Total cases'), width = 4),
dbc.Col(html.H6('People fully vaccinated'), width = 4)])
],
body = True
)
This should be an interactive feature that depends on two selectors: The first selector is the variable, and the user should be able to select between the following variables: Deaths, Cases, Vaccinations
The second selector is the metric, which should depend on the chosen variable. If the user has chosen “Deaths” or “Cases,then the available metrics should be: Total, Total per 1 million population, Newley reported in the last 24 hours
However, if the user has selected “Vaccinations”, then the available metrics should be: Total doses administered per 100 population, Persons vaccinated with at least one dose per 100 population, Persons fully vaccinated with last dose of primary series
# create the selector metric
death_options = [
{'label' : 'Total', 'value' : 'total_deaths'},
{'label' : 'Total per 1 million population', 'value' : 'total_deaths_per_million'},
{'label' : 'Newley reported in the last 24 hours', 'value' : 'new_deaths'}
]
case_options= [
{'label' : 'Total', 'value' : 'total_cases'},
{'label' : 'Total per 1 million population', 'value' : 'total_cases_per_million'},
{'label' : 'Newley reported in the last 24 hours', 'value' : 'new_cases'}]
vaccine_options = [
{'label' : 'Total doses administered per 100 population', 'value' : 'total_vaccinations_per_hundred'},
{'label' : 'Persons vaccinated with at least one dose per 100 population', 'value' : 'people_vaccinated_per_hundred'},
{'label' : 'Persons fully vaccinated with last dose of primary series', 'value' : 'people_fully_vaccinated'}
]
choices = {
"total_deaths": death_options,
"total_cases": case_options,
"people_fully_vaccinated": vaccine_options,
}
variable_dropdown1 = dcc.Dropdown(
id = 'my_variable1',
options = [
{'label' : 'Deaths', 'value' : 'total_deaths'},
{'label' : 'Cases', 'value' : 'total_cases'},
{'label' : 'Vaccinations', 'value' : 'people_fully_vaccinated'}],
value = 'total_deaths'
)
variable_dropdown2 = dcc.Dropdown(
id = 'my_variable2',
options = choices['total_deaths'],
value = 'total_deaths'
)
variable_dropdown3 = dcc.Dropdown(
id = 'my_variable3',
options = [
{'label' : 'Deaths', 'value' : 'total_deaths'},
{'label' : 'Cases', 'value' : 'total_cases'},
{'label' : 'Vaccinations', 'value' : 'people_fully_vaccinated'}],
value = 'total_deaths'
)
# sum each variable in each country
covid19_df2 = covid19_df.groupby('iso_code').sum().reset_index()
covid19_df2
card2 = dbc.Card( #create a second card component
children = [
html.H4('Word Map of COVID-19', className = 'card-title'),
html.P('A world map that shows the number of deaths, cases and vaccinations for each country in the data set.', className = 'card-text'),
dbc.Row(
children = [variable_dropdown1, variable_dropdown2]
),
dcc.Graph(id = 'my_map')
],
body = True
)
This feature should also be an interactive feature, but it should only depend on the chosen variable. When the user selects one of the available variables (“Deaths”, “Cases” and “Vaccinations”), the bar plot should display the global number of new occurrences for that variable in each week of the data set.
#sum each variable in each week
covid19_df['date'] = pd.to_datetime(covid19_df['date'])
covid19_df3 = covid19_df.resample('W', on = 'date').sum().reset_index()
covid19_df3
card3 = dbc.Card( # create a third card component
children = [
html.H4('Bar Plot', className = 'card-title'),
html.P('A bar plot that shows the global number of new deaths, cases and vaccinations for each week in the data set.', className = 'card-text'),
dbc.Row(
dbc.Col([html.Label('Select variable:'),variable_dropdown3], width = 6)
),
dcc.Graph(id = 'my_barplot')
],
body = True
)
app = JupyterDash(external_stylesheets = [dbc.themes.BOOTSTRAP, dbc_css])
app.layout = dbc.Container(
children = [
# header
html.H1('COVID-19 Dashboard'),
dcc.Markdown(
"""Data on daily observations on COVID-19 are extracted from the
[Our World in Data](https://covid.ourworldindata.org/data/owid-covid-data.csv)
database."""
),
# insert cards
card1,
html.Br(),
card2,
html.Br(),
card3,
html.Br(),
],
className = 'dbc'
)
@app.callback(
Output('my_variable2', component_property="options"),
Output('my_variable2', component_property="value"),
Input('my_variable1', component_property="value")
)
def update_dropdown(choice):
return choices[choice], choices[choice][0]['value']
@app.callback(
Output('my_map', 'figure'),
Input('my_variable2', 'value'),
)
def update_map(metric):
dff = covid19_df2
map=px.choropleth(
dff,
locations = dff['iso_code'],
color = metric,
color_continuous_scale = 'blues',
hover_name = 'iso_code',
hover_data = {'iso_code' : False},
)
map.update_layout(
coloraxis_colorbar_title = None,
geo_showframe = False,
margin = {'l' : 0, 'r' : 0, 'b' : 0, 't' : 0}
)
return(map)
@app.callback(
Output('my_barplot', 'figure'),
Input('my_variable3', 'value')
)
def update_bar_plot(variable):
dff = covid19_df3
barchart=px.bar(
data_frame=dff,
x=dff['date'],
y=dff[variable])
return(barchart)
app.run_server(port = 3420)