- First time
- Every time
- How to
- Run the app
- See installed packages
- Install packages
- Launch Jupyter Notebook
- Change the app name in the browser title bar
- Change the app name in the navigation bar
- Change your name and contact info in the footer
- Change Bootswatch theme
- Change navigation bar colors
- Change home page text & button
- Add a page
- Remove a page
- Add an image
- Add a matplotlib plot
- Add a Plotly plot
- Add a scikit-learn pipeline
- Exit the Pipenv shell
- Deploy to Heroku
You need this software on your local computer:
- Python 3. I recommend Anaconda Distribution.
- Git. If you're on Windows, I recommend Git for Windows. If you're on Mac or Linux, Git is built in.
- A terminal. If you're on Windows, I recommend Anaconda Prompt. If you're on Mac or Linux, a terminal is built in.
- 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.
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>
If you're on Windows, delete the Pipfile.lock
file.
Create a virtual environment for this project, and install dependencies from Pipfile:
pipenv install
Next, activate the Pipenv shell & run the app!
cd <repo>
pipenv shell
You can verify your virtual environment is active:
- Look at your command prompt prefix
- 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
python run.py
Then in your browser, go to http://localhost:8050/
Ctrl+C quits the app.
Pipfile
is a plain text file that lists the packages installed in the virtual environment. If you open the Pipfile
file in any text editor software, you can view its contents. It will look something 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"
pipenv install <package>
For example, to install scikit-learn, category_encoders, xgboost, & Dash DAQ:
pipenv install scikit-learn category_encoders xgboost dash_daq
First, don't forget to activate the Pipenv shell. Then:
jupyter notebook
Edit app.py
file, app.title
string:
app.title = 'YOUR APP NAME' # appears in browser title bar
Edit run.py
file, navbar
object, brand
string:
navbar = dbc.NavbarSimple(
brand='YOUR APP NAME',
...
)
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.
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)
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 thenavbar-light
class to the NavbarSimple, causing text in the children of the Navbar to use dark colors for contrast / visibility.
dark
(boolean, optional): Applies thenavbar-dark
class to the NavbarSimple, causing text in the children of the Navbar to use light colors for contrast / visibility.
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,
)
The RUN app example comes from Google's People + AI Guidebook.
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')),
],
...
)
-
Edit
run.py
file,navbar
object. Remove thedbc.NavItem
&dcc.Link
objects for the page. -
Edit
run.py
file. Do not import<pagename>
from thepages
module. -
Edit
run.py
file,display_page
function. Remove the code block that returns<pagename>.layout
whenpathname == '/<pagename>'
-
Delete the file,
pages/<pagename>.py
-
Put the image file
<imagefile.extension>
in theassets/
directory. -
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.
This includes visualization libraries that run on top of Matplotlib:
- Pandas plotting
- PDPBox
- Seaborn
- SHAP
force_plot
withmatplotlib=True
parameter
First, you should set matplotlib dots per inch to at least 150, so the text isn't fuzzy.
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 150
Then take a screenshot or save the plot as an image, and follow the instructions to add an image.
Get it working in your notebook first. For example:
%matplotlib inline
import matplotlib.pyplot as plt
matplotlib_figure = plt.figure()
x = [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]
y = [ 8, 6, 7, 8, 8, 9, 7, 4, 10, 4, 5]
plt.scatter(x, y)
Then convert the matplotlib figure to a Plotly figure in your notebook, and test that it works:
from plotly.tools import mpl_to_plotly
plotly_figure = mpl_to_plotly(matplotlib_figure)
plotly_figure.show()
After it works in your notebook, put it in your app, with a Dash Graph component:
import dash_core_components as dcc
import matplotlib.pyplot as plt
from plotly.tools import mpl_to_plotly
matplotlib_figure = plt.figure()
x = [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]
y = [ 8, 6, 7, 8, 8, 9, 7, 4, 10, 4, 5]
plt.scatter(x, y)
plotly_figure = mpl_to_plotly(matplotlib_figure)
layout = dcc.Graph(id='my-graph-name', figure=plotly_figure)
Follow the instructions in the official Dash tutorial, or see the example included in pages/index.py
.
- Activate the Pipenv shell
- Install packages (scikit-learn, anything else you want)
- Launch Jupyter Notebook
- 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)
from joblib import dump
dump(pipeline, 'pipeline.joblib')
-
Copy the file
pipeline.joblib
into theassets/
directory. -
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')
- 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,
)
- Add Dash component for output. For example:
column2 = dbc.Col(
[
html.H2('Expected Lifespan', className='mb-5'),
html.Div(id='prediction-content', className='lead')
]
)
- 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
-
Watch DS - Data Engineering - Productization and Cloud - Web Application Deployment (12 minute video from Training Kit).
-
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
-
Download and install Heroku CLI (Command Line Interface) https://devcenter.heroku.com/articles/heroku-cli
-
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.)
-
Go to https://dashboard.heroku.com/new-app and give your app a name.
-
Follow the commands that Heroku gives you. For example:
heroku login
heroku git:remote -a your-app-name
- 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 installProcfile
tells Heroku what command to run.slugignore
tells Heroku what files to ignore