Skip to content

Plotly Dash web app to predict and display US State GDP Growth by Industry

License

Notifications You must be signed in to change notification settings

noreallyimfine/gdp-growth-dash-app

Repository files navigation

dash-template

First time

Requirements

You need this software on your local computer:

  • A terminal. If you're on Windows, I recommend Git Bash. If you're on Mac or Linux, a terminal is built in.
  • Python 3. I recommend Anaconda Distribution.
  • An IDE (Integrated Development Environment) or text editor. I recommend VS Code.

You also need to install Pipenv.

pip install pipenv

It automatically creates and manages a virtualenv for your projects, as well as adds/removes packages from your Pipfile as you install/uninstall packages. It also generates the ever-important Pipfile.lock, which is used to produce deterministic builds.

Setup

Create a new repository from this template.

Clone the repo onto your local computer:

git clone https://github.com/<you>/<repo>.git

Change directory into the repo:

cd <repo>

Create a virtual environment for this project, and install dependencies from Pipfile.lock:

pipenv install

Next, activate the Pipenv shell & run the app!

Every time

Change directory into the repo

cd <repo>

Activate the Pipenv shell

pipenv shell

You can verify your virtual environment is active:

  1. Look at your command prompt prefix
  2. Run the command which jupyter

✅ You should see this:

(your-repo-name) $ which jupyter
/Users/you/.local/share/virtualenvs/your-repo-name/bin/jupyter

❌ Not this:

(base) $ which jupyter
/anaconda3/bin/jupyter

How to

Run the app

python run.py

Then in your browser, go to http://localhost:8050/

Ctrl+C quits the app.

See installed packages

cat Procfile

You'll see output like this:

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
dash = "*"
dash-bootstrap-components = "*"
gunicorn = "*"
plotly = "*"
jupyter = "*"
pandas = "*"

[requires]
python_version = "3.7"

Install packages

pipenv install <package>

For example, to install scikit-learn, category_encoders, xgboost, & Dash DAQ:

pipenv install scikit-learn category_encoders xgboost dash_daq

Launch Jupyter Notebook

First, don't forget to activate the Pipenv shell. Then:

jupyter notebook

Change the app name in the browser title bar

Edit app.py file, app.title string:

app.title = 'YOUR APP NAME' # appears in browser title bar

Change the app name in the navigation bar

Edit run.py file, navbar object, brand string:

navbar = dbc.NavbarSimple(
    brand='YOUR APP NAME',
    ...
)

Change your name and contact info in the footer

Edit run.py file, footer object:

footer = dbc.Container(
    dbc.Row(
        dbc.Col(
            html.P(
                [
                    html.Span('Your Name', className='mr-2'), 
                    html.A(html.I(className='fas fa-envelope-square mr-1'), href='mailto:<you>@<provider>.com'), 
                    html.A(html.I(className='fab fa-github-square mr-1'), href='https://github.com/<you>/<repo>'), 
                    html.A(html.I(className='fab fa-linkedin mr-1'), href='https://www.linkedin.com/in/<you>/'), 
                    html.A(html.I(className='fab fa-twitter-square mr-1'), href='https://twitter.com/<you>'), 
                ], 
                className='lead'
            )
        )
    )
)

Dash components use the className parameter for CSS classes. fa stands for Font Awesome and is used for social media icons. mr stands for "margin right" and these CSS classes are from Bootstrap. The class lead is also from Bootstrap to make "lead" paragraphs stand out more. You can add & remove CSS classes if you want.

Change Bootswatch theme

Browse themes at https://bootswatch.com/

  • dbc.themes.BOOTSTRAP
  • dbc.themes.CERULEAN
  • dbc.themes.COSMO
  • dbc.themes.CYBORG
  • dbc.themes.DARKLY
  • dbc.themes.FLATLY
  • dbc.themes.JOURNAL
  • dbc.themes.LITERA
  • dbc.themes.LUMEN
  • dbc.themes.LUX
  • dbc.themes.MATERIA
  • dbc.themes.MINTY
  • dbc.themes.PULSE
  • dbc.themes.SANDSTONE
  • dbc.themes.SIMPLEX
  • dbc.themes.SKETCHY
  • dbc.themes.SLATE
  • dbc.themes.SOLAR
  • dbc.themes.SPACELAB
  • dbc.themes.SUPERHERO
  • dbc.themes.UNITED
  • dbc.themes.YETI

Edit app.py file, external_stylesheets parameter:

external_stylesheets = [
    dbc.themes.BOOTSTRAP, # Bootswatch theme
    'https://use.fontawesome.com/releases/v5.9.0/css/all.css', # for social media icons
]

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

Change navigation bar colors

First, choose your Bootswatch theme.

Then, edit run.py file, navbar object, color, light & dark parameters:

navbar = dbc.NavbarSimple(
    ...
    color='light', 
    light=True, 
    dark=False
)

These parameters are explained in Dash Bootstrap Components docs:

color (string, optional): Sets the color of the NavbarSimple. Main options are primary, light and dark, default light. You can also choose one of the other contextual classes provided by Bootstrap (secondary, success, warning, danger, info, white) or any valid CSS color of your choice (e.g. a hex code, a decimal code or a CSS color name)

light (boolean, optional): Applies the navbar-light class to the NavbarSimple, causing text in the children of the Navbar to use dark colors for contrast / visibility.

dark (boolean, optional): Applies the navbar-dark class to the NavbarSimple, causing text in the children of the Navbar to use light colors for contrast / visibility.

Change home page text & button

Edit pages/index.py file, column1 object:

column1 = dbc.Col(
    [
        dcc.Markdown(
            """
        
            ## Value Proposition

            Emphasize how the app will benefit users. Don't emphasize the underlying technology.

            ✅ RUN is a running app that adapts to your fitness levels and designs personalized workouts to help you improve your running.

            ❌ RUN is the only intelligent running app that uses sophisticated deep neural net machine learning to make your run smarter because we believe in ML driven workouts.

            """
        ),
        dcc.Link(dbc.Button('Call To Action', color='primary'), href='/predictions')
    ],
    md=4,
)

Docs

The RUN app example comes from Google's People + AI Guidebook.

Add a page

1. Make a new file, pages/pagename.py

The code should have an object named layout, with a Dash component assigned to it. For example:

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

from app import app

column1 = dbc.Col(
    [
        dcc.Markdown(
            """
        
            ## PAGE NAME


            """
        ),
    ],
    md=4,
)

column2 = dbc.Col([])

layout = dbc.Row([column1, column2])

This layout is explained in Dash Bootstrap Components docs:

The Bootstrap grid has twelve columns. The layout of your app should be built as a series of rows of columns.

We set md=4 indicating that on a 'medium' sized or larger screen the column should take up a third of the width. Since we don't specify behaviour on smaller size screens Bootstrap will allow the rows to wrap so as not to squash the content.

2. Edit run.py file. Import <pagename> from the pages module.

from pages import index, predictions, insights, process, pagename

3. Edit run.py file, display_page function. Return <pagename>.layout when pathname == '/<pagename>'

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/':
        return index.layout
    elif pathname == '/predictions':
        return predictions.layout
    elif pathname == '/insights':
        return insights.layout
    elif pathname == '/process':
        return process.layout
    elif pathname == '/pagename':
        return pagename.layout
    else:
        return dcc.Markdown('## Page not found')

4. Edit run.py file, navbar object. Add dbc.NavItem & dcc.Link objects for the page.

navbar = dbc.NavbarSimple(
    children=[
        dbc.NavItem(dcc.Link('Predictions', href='/predictions', className='nav-link')), 
        dbc.NavItem(dcc.Link('Insights', href='/insights', className='nav-link')), 
        dbc.NavItem(dcc.Link('Process', href='/process', className='nav-link')), 
        dbc.NavItem(dcc.Link('Page Name', href='/pagename', classname='nav-link')), 
    ],
    ...
)

Remove a page

  1. Edit run.py file, navbar object. Remove the dbc.NavItem & dcc.Link objects for the page.

  2. Edit run.py file. Do not import <pagename> from the pages module.

  3. Edit run.py file, display_page function. Remove the code block that returns <pagename>.layout when pathname == '/<pagename>'

  4. Delete the file, pages/<pagename>.py

Add an image

  1. Put the image file <imagefile.extension> in the assets/ directory.

  2. Edit the file, pages/<pagename>.py. Add a Dash HTML Img component in the layout:

html.Img(src='assets/imagefile.extension', className='img-fluid')

You can size and position images with Boostrap (for example, with the img-fluid class) or just with CSS.

Add a scikit-learn pipeline

  1. Activate the Pipenv shell
  2. Install packages (scikit-learn, anything else you want)
  3. Launch Jupyter Notebook
  4. In your notebook, fit your pipeline. For example:
import category_encoders as ce
import plotly.express as px
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline

gapminder = px.data.gapminder()
X = gapminder[['year', 'continent']]
y = gapminder['lifeExp']

pipeline = make_pipeline(
    ce.OneHotEncoder(use_cat_names=True), 
    LinearRegression()
)

pipeline.fit(X, y)
  1. "Pickle" the pipeline:
from joblib import dump
dump(pipeline, 'pipeline.joblib')
  1. Copy the file pipeline.joblib into the assets/ directory.

  2. Edit the file, pages/<pagename>.py. Add this code at the top, to load the pipeline.

from joblib import load
pipeline = load('assets/pipeline.joblib')
  1. Add Dash components for inputs. For example:
column1 = dbc.Col(
    [
        dcc.Markdown('## Predictions', className='mb-5'), 
        dcc.Markdown('#### Year'), 
        dcc.Slider(
            id='year', 
            min=1955, 
            max=2055, 
            step=5, 
            value=2020, 
            marks={n: str(n) for n in range(1960,2060,20)}, 
            className='mb-5', 
        ), 
        dcc.Markdown('#### Continent'), 
        dcc.Dropdown(
            id='continent', 
            options = [
                {'label': 'Africa', 'value': 'Africa'}, 
                {'label': 'Americas', 'value': 'Americas'}, 
                {'label': 'Asia', 'value': 'Asia'}, 
                {'label': 'Europe', 'value': 'Europe'}, 
                {'label': 'Oceania', 'value': 'Oceania'}, 
            ], 
            value = 'Africa', 
            className='mb-5', 
        ), 
    ],
    md=4,
)
  1. Add Dash component for output. For example:
column2 = dbc.Col(
    [
        html.H2('Expected Lifespan', className='mb-5'), 
        html.Div(id='prediction-content', className='lead')
    ]
)
  1. Add callback to update output based on inputs. For example:
import pandas as pd

@app.callback(
    Output('prediction-content', 'children'),
    [Input('year', 'value'), Input('continent', 'value')],
)
def predict(year, continent):
    df = pd.DataFrame(
        columns=['year', 'continent'], 
        data=[[year, continent]]
    )
    y_pred = pipeline.predict(df)[0]
    return f'{y_pred:.0f} years'

Exit the Pipenv shell

exit

Deploy to Heroku

  1. Watch DS - Data Engineering - Productization and Cloud - Web Application Deployment (12 minute video from Training Kit).

  2. Sign up for Heroku at https://signup.heroku.com/ for a free account.

If you are registered with the GitHub Student Developer Pack, you are eligible to receive one free Hobby Dyno for up to 2 years (valued at $84/year). (App never sleeps) — https://www.heroku.com/github-students

  1. Download and install Heroku CLI (Command Line Interface) https://devcenter.heroku.com/articles/heroku-cli

  2. Change directory into the repo & activate the Pipenv shell.

  3. Test your app locally, with Gunicorn:

gunicorn run:server

(Note, on Windows, there may be problems with Gunicorn, so you don't have to test locally with it, instead you can just use python run.py like before.)

  1. Go to https://dashboard.heroku.com/new-app and give your app a name.

  2. Follow the commands that Heroku gives you. For example:

heroku login

heroku git:remote -a your-app-name
  1. Deploy to Heroku:
git push heroku master

Then Heroku will set up everything, launch your app, and give you the URL!

How does Heroku know what to do? Because of these files in the repo:

  • Pipfile.lock tells Heroku what libraries & versions to install
  • Procfile tells Heroku what command to run
  • .slugignore tells Heroku what files to ignore

About

Plotly Dash web app to predict and display US State GDP Growth by Industry

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published