Check out other post about the dashboard
- Getting data from US BLS open data using BLS API key
- Getting data from US EIA website using EIA API key
- Python Dashboard available here
- Full Code available on GitHub
Building the New Layout
For the new layout of the dashboard, I wanted something more modular. The previous version felt like it was too cramped, so this time I wanted to make them more separate. I also wanted to separate the code into different files, making it easier to read.
First I created a new file called layout_functions.py, this file contains all components such as the date picker, graphs, and layout containers.
# Import libraries required for building the dashboard
import pandas as pd
import datetime
from dash import html
from dash import dcc
from dash.dependencies import Input, Output
def header():
header_layout = html.Div(
id='header',
className='header',
children=[
html.Div(
children=[
html.H1(
children='CPI DashBoard',
className='header-title'
),
html.H2(children='Visualizing CPI and Different Commodity',
className='header-description')
],
)
]
)
return header_layout
def date_picker(data):
range_picker = html.Div(
children=[
dcc.DatePickerRange(
id='date_range',
className='date_picker_container',
min_date_allowed=data['year_month'].min(),
max_date_allowed=data['year_month'].max(),
start_date=data['year_month'].min(),
end_date=data['year_month'].max(),
initial_visible_month=data['year_month'].max()
)
]
)
return range_picker
def drop_down():
menu = dcc.Dropdown(
id='drop_down_menu',
className='drop_down_menu',
options=[
{'label': 'Commodity Prices', 'value': 'Commodity Prices'},
{'label': 'Crude Oil Spot Price', 'value': 'Crude Oil Spot Price'},
{'label': 'Crude Oil Production', 'value': 'Crude Oil Production'},
{'label': 'Crude Oil Consumption', 'value': 'Crude Oil Consumption'}
],
value='Commodity Prices'
)
return menu
def cpi_line_graph():
line_graph = dcc.Graph(
id='cpi_chart',
className='card',
config={'displayModeBar': True},
)
return line_graph
def line_graph():
line_graph = dcc.Graph(
id='line_chart',
className='card',
config={'displayModeBar': True}
)
return line_graph
header is the top part of the dashboard, it contains the title and the description of the dashboard.
date_picker allows the ability to select the date range of the data to visualize.
drop_down is the drop down menu for selecting different data to visualize.
cpi_line_graph and line_graph are used for displaying the data via line graphs.
Now that I have the functions for the component, I can start to build the dashboard. The following visualization can help understand the layout of the dashboard.
black border: Contain everything
Red border: Header
Yellow border: Sidebar
Green border: Date picker, Drop down menu, Graphs
To achieve this, I created a new file layout.py that houses all the containers.
import dash
from layout_functions.layout_functions import *
from data.data_update.fetch_data import *
bls_data = pd.read_csv('./data/bls_data.csv')
eia_petroleum_spot = pd.read_csv('./data/eia_crude_price.csv')
eia_api_crude_production = pd.read_csv('./data/eia_crude_production.csv')
eia_api_crude_consumption = pd.read_csv('./data/eia_crude_consumption.csv')
external_stylesheets = [
{
"href": "https://fonts.googleapis.com/css2?"
"family=Lato:wght@400;700&display=swap",
"rel": "stylesheet",
}
]
# Initialize the dash class
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
app.title = 'CPI Dashboard'
app.layout = html.Div(
children=[
html.Div(
header()
),
html.Div(
children=[
html.Div(
id='sidebar',
className='sidebar',
children=[
dcc.Markdown('''
## About this Project
This project is a dashboard for visualizing the CPI levels and different
prices.
Full Code: [Github](https://github.com/thecodingmango/cpi_dashboard)
Website: [TheCodingMango](https://thecodingmango.com/)
''')
]
),
html.Div(
id='main',
className='card',
children=[
# Date picker section
html.Div(
className='main_top',
children=[
date_picker(bls_data),
drop_down()
]
),
# CPI chart
html.Div(
className='cpi_chart_container',
children=[cpi_line_graph()]
),
# Other Charts
html.Div(
className='line_chart_container',
children=[line_graph()]
)
]
)
],
className='content_wrapper'
)
],
className='wrapper'
)
However, there is still a missing piece to the dashboard, if I want the dashboard to update when user interacts with it, I have to put in an app.callback for the dashboard to update.
@app.callback(
[Output('cpi_chart', 'figure'),
Output('line_chart', 'figure')],
[Input('date_range', 'start_date'),
Input('date_range', 'end_date'),
Input('drop_down_menu', 'value')]
)
def update_chart(start_date, end_date, value):
temp_list = []
filters_date_bls = ((bls_data['year_month'] >= start_date) & (bls_data['year_month'] <= end_date))
filtered_data_bls = bls_data.loc[filters_date_bls, :]
cpi_chart = {
'data': [
{
'x': filtered_data_bls['year_month'],
'y': filtered_data_bls['cpi_values'],
'type': 'lines',
'name': 'CPI_Values'
}
],
'layout': {
'title': {
'text': 'CPI Values Since' + ' ' + start_date,
'x': 'center'
},
'xaxis': {
'title': 'Year',
},
'yaxis': {
'title': {'text': 'CPI Values',
'font-size': 'bold'
},
'ticksuffix': '%',
'font': 'bold'
},
'height': 400
}
}
if value == 'Commodity Prices':
for series in filtered_data_bls.columns[1:-2]:
temp_list += [
{'x': filtered_data_bls['year_month'], 'y': filtered_data_bls[series],
'type': 'lines',
'name': series
}
]
line_chart = {
'data':
temp_list
,
'layout': {
'title': {
'text': 'Comparison of Different Commodity Prices' + ' Since ' + start_date,
'x': 'center'
},
'xaxis': {
'title': ' Year'
},
'yaxis': {
'title': ' Prices in USD'
},
'height': 400
}
}
return [cpi_chart, line_chart]
elif value == 'Crude Oil Spot Price':
eia_filter = ((eia_petroleum_spot['year_month'] >= start_date) &
(eia_petroleum_spot['year_month'] <= end_date))
eia_petro_price = eia_petroleum_spot.loc[eia_filter, :]
for series in eia_petro_price.columns[1:-1]:
temp_list += [
{
'x': eia_petro_price['year_month'],
'y': eia_petro_price[series],
'type': 'lines',
'name': series
}
]
line_chart = {
'data':
temp_list,
'layout': {
'title': {
'text': 'Comparison of Crude Oil Spot Prices' + ' Since ' + start_date,
'x': 'center'
},
'xaxis': {
'title': ' Year'
},
'yaxis': {
'title': ' Prices USD'
},
'height': 400
}
}
return [cpi_chart, line_chart]
elif value == 'Crude Oil Production':
eia_filter_production = ((eia_api_crude_production['year_month'] >= start_date) &
(eia_api_crude_production['year_month'] <= end_date))
eia_oil_production = eia_api_crude_production.loc[eia_filter_production, :]
for series in eia_oil_production.columns[1:-1]:
temp_list += [
{
'x': eia_oil_production['year_month'],
'y': eia_oil_production[series],
'type': 'lines',
'name': series
}
]
line_chart = {
'data':
temp_list,
'layout': {
'title': {
'text': 'Comparison of Different Oil Production Level by Country' + ' Since ' + start_date,
'x': 'center'
},
'xaxis': {
'title': ' Year'
},
'yaxis': {
'title': ' Million of Barrel (s)'
},
'height': 400
}
}
return [cpi_chart, line_chart]
elif value == 'Crude Oil Consumption':
eia_filter_consumption = ((eia_api_crude_consumption['year_month'] >= start_date) &
(eia_api_crude_consumption['year_month'] <= end_date))
eia_oil_consumption = eia_api_crude_production.loc[eia_filter_consumption, :]
for series in eia_oil_consumption.columns[1:-1]:
temp_list += [
{
'x': eia_oil_consumption['year_month'],
'y': eia_oil_consumption[series],
'type': 'lines',
'name': series
}
]
line_chart = {
'data':
temp_list,
'layout': {
'title': {
'text': 'Comparison of Different Oil Consumption Level by Country' + ' Since ' + start_date,
'x': 'center'
},
'xaxis': {
'title': ' Year'
},
'yaxis': {
'title': ' Million of Barrel (s)'
},
'height': 400
}
}
return [cpi_chart, line_chart]
Finally, I created cpi_dashboard.py to run everything.
# Import libraries
from layout import app
if __name__ == "__main__":
app.run_server(debug=True)