{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Getting Started With `plotly` and `dash` in Python\n",
"\n",
"\n",
"This tutorial is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.\n",
"\n",
"## Acknowledgements\n",
"\n",
"The author consulted the following resources when writing this tutorial:\n",
"- [`plotly` documentation and tutorials](https://plotly.com/python/)\n",
"- [`dash` documentation and tutorials](https://dash.plotly.com/)\n",
"\n",
"# Table of Contents\n",
"\n",
"- [Overview](#overview)\n",
" * [Basic `dash` Syntax](#basic-dash-syntax)\n",
" * [Customizing `dash` Layout with `dash_html_components`](#customizing-dash-layout-with-dash-html-components)\n",
" * [Customizing `dash` Layout with `dash_core_components`](#customizing-dash-layout-with-dash-core-components)\n",
" * [Setting Up Callbacks](#setting-up-callbacks)\n",
" * [Additional Resources](#additional-resources)\n",
" * [Publishing a `dash` App](#publishing-a-dash-app)\n",
"\n",
"# Overview\n",
"\n",
"1. We may want to create an interactive web application featuring a `plotly` figure.\n",
"\n",
"2. We see this kind of interactivity in dashboard-style interfaces, like the [Johns Hopkins University COVID-19 Dashboard](https://coronavirus.jhu.edu/map.html).\n",
"\n",
"3. We can use the `dash` web application framework in combination with `plotly` to \"publish\" a figure as an interactive web application.\n",
"\n",
"4. `dash` was developed by the Plotly team and released in 2017.\n",
"\n",
"5. In addition to a limited free open-source version, Plotly also offers paid enterprise versions of `dash`.\n",
"\n",
"6. What exactly is `dash`?\n",
"\n",
"7. \"Dash is a productive Python framework for building web analytic applications. Written on top of Flask, Plotly.js, and React.js, Dash is ideal for building data visualization apps with highly custom user interfaces in pure Python. It's particularly suited for anyone who works with data in Python. Through a couple of simple patterns, Dash abstracts away all of the technologies and protocols that are required to build an interactive web-based application. Dash is simple enough that you can bind a user interface around your Python code in an afternoon. Dash apps are rendered in the web browser. You can deploy your apps to servers and then share them through URLs. Since Dash apps are viewed in the web browser, Dash is inherently cross-platform and mobile ready\" (`plotly`, [Introduction to Dash](https://dash.plotly.com/introduction)).\n",
"\n",
"8. For those familiar with RStudio's [Shiny package](v) (designed to build interactive web applications from within the R/RStudio programming environment), `dash` was originally pitched as the equivalent package for Python.\n",
"\n",
"9. Though originally built exclusively for `Python`, `dash` has since released versions for R/RStudio and Julia.\n",
"\n",
"10. For more background on `dash`:\n",
"- plotly, [\"Introducing Dash\"](https://medium.com/plotly/introducing-dash-5ecf7191b503) *Medium* (21 June 2017)\n",
"- Plotly, [\"PLOTCON 2016: Chris Parmer, Dash: Shiny for Python\"](https://youtu.be/5BAthiN0htc) *YouTube* (1 December 2016)\n",
"- `plotly`, [Dash Enterprise App Gallery](https://dash-gallery.plotly.host/Portal/)\n",
"- [Plotly, Dash GitHub repository](https://github.com/plotly/dash)\n",
"\n",
"11. To install `dash`:\n",
"- using `pip`: `pip install dash`\n",
"- in Jupyter notebook using `pip`: `pip install jupyter-dash`\n",
"- in Jupyter notebook using `conda`: `conda install -c conda-forge -c plotly jupyter-dash`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"!{sys.executable} -m pip install jupyter-dash"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"12. The remainder of this tutorial focuses on `dash` outside the Jupyter notebook environment.\n",
"\n",
"13. For more on using `dash` in a notebook environment: plotly, [Jupyter-Dash Github Repository](https://github.com/plotly/jupyter-dash)\n",
"\n",
"## Basic `dash` Syntax\n",
"\n",
"14. `dash` apps include two main components.\n",
"\n",
"15. The app ***layout*** describes what the application looks like.\n",
"\n",
"16. The app ***interactivity*** describes the application's interactivity.\n",
"\n",
"17. `dash` uses pre-built Python classes for all visual components of the application (which can be customized if needed using JavaScript and React.js).\n",
"\n",
"18. The basic syntax for creating an application using `dash`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# at this point the figure has already been created and updated/configured/customized as needed\n",
"\n",
"# import dash components\n",
"import dash\n",
"import dash_core_components as dcc\n",
"import dash_html_components as html\n",
"\n",
"# create app\n",
"app = dash.Dash()\n",
"\n",
"# set app layout\n",
"app.layout = html.Div([\n",
" dcc.Graph(figure=fig)\n",
"])\n",
"\n",
"# run app\n",
"app.run_server(debug=True, use_reloader=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"19. Let's create an app using our tile-based choropleth map."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# import urllib\n",
"from urllib.request import urlopen\n",
"\n",
"# import json\n",
"import json\n",
"\n",
"# load geojson data\n",
"with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:\n",
" counties = json.load(response)\n",
"\n",
"# import pandas\n",
"import pandas as pd\n",
"\n",
"# load attribute data as dataframe\n",
"df = pd.read_csv(\"https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv\",\n",
" dtype={\"fips\": str})\n",
"\n",
"# import plotly\n",
"import plotly.express as px\n",
"\n",
"# create figure\n",
"fig = px.choropleth_mapbox(df, geojson=counties, locations='fips', color='unemp',\n",
" color_continuous_scale=\"Viridis\",\n",
" range_color=(0, 12),\n",
" mapbox_style=\"carto-positron\",\n",
" zoom=3, center = {\"lat\": 37.0902, \"lon\": -95.7129},\n",
" opacity=0.5,\n",
" labels={'unemp':'unemployment rate'}\n",
" )\n",
"\n",
"# update figure layout\n",
"fig.update_layout(margin={\"r\":0,\"t\":0,\"l\":0,\"b\":0})\n",
"\n",
"# show figure\n",
"fig.show()\n",
"\n",
"# import dash components\n",
"import dash\n",
"import dash_core_components as dcc\n",
"import dash_html_components as html\n",
"\n",
"# create app\n",
"app = dash.Dash()\n",
"\n",
"# set app layout\n",
"app.layout = html.Div([\n",
" dcc.Graph(figure=fig)\n",
"])\n",
"\n",
"# run app\n",
"app.run_server(debug=True, use_reloader=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"20. At the bottom of each documentation page for a `plotly` figure type will be a \"What About Dash?\" section that provides a brief overview of how to publish that figure in a `dash` application.\n",
"\n",
"21. For example, [link to the \"What About Dash?\"](https://plotly.com/python/scattermapbox/#what-about-dash) section of the \"Scatter Plots on Mapbox in Python\" page.\n",
"\n",
"## Customizing `dash` Layout with `dash_html_components`\n",
"\n",
"22. This example makes very few modifications to `app.layout`.\n",
"\n",
"23. We can start to customize a `dash` app by using an external style sheet.\n",
"\n",
"24. Similar to how we use CSS in combination with HTML, external style sheets can also be loaded and applied in `dash`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# load style sheet; this example uses URL; could also use local .css file\n",
"external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']\n",
"\n",
"# call style sheet when starting app\n",
"app = dash.Dash(APP_NAME, external_stylesheets=external_stylesheets)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"25. We can also start to modify components of the application by declaring HTML tags.\n",
"\n",
"26. Remember in HTML, tags like `
`, etc. are used for styling and formatting.\n", "\n", "27. The `dash_html_components` library has a component for every HTML tag.\n", "\n", "28. We can create declarations for those elements to govern how they are formatted or styled in the `dash` application.\n", "\n", "29. This is similar to how we create declarations in an external style sheet.\n", "\n", "30. Let's modify our app layout to include a `H1` title, a `div` subtitle, and a `Graph` object." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# omitted code creates and customizes figure\n", "\n", "# import dash components\n", "import dash\n", "import dash_core_components as dcc\n", "import dash_html_components as html\n", "\n", "# load style sheet; this example uses URL; could also use local .css file\n", "external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']\n", "\n", "# call style sheet when starting app\n", "app = dash.Dash(Test_App, external_stylesheets=external_stylesheets)\n", "\n", "# set app layout\n", "app.layout = html.Div(children=[\n", " html.H1(children='Hello Dash'),\n", "\n", " html.Div(children='''\n", " Dash: A web application framework for Python.\n", " '''),\n", "\n", " dcc.Graph(\n", " id='example-graph',\n", " figure=fig\n", " )\n", "])\n", "\n", "# run app\n", "app.run_server(debug=True, use_reloader=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "32. We see the component declarations nested under `app.layout`.\n", "\n", "33. `dash` generates an HTML element for each of these components.\n", "\n", "34. For example, `dash` takes `html.H1(children='Hello Dash')` and generates `