Plotly Dash: From Development to Deployment | by Anshul Sharma | Towards Data Science

Plotly Dash is an amazing framework to build interactive dashboards purely using Python. As a dashboard is akin to a website, definitely a bit of HTML & CSS is also involved, but be rest assured it is so rudimentary that even I learned it while creating my first dashboard.
In this tutorial, we will be building a COVID19 dashboard showing the growth/decline of COVID19 cases, recoveries, and deaths in India. The dashboard can be accessed using this link and the underlying code can be accessed using this GitHub repository.
Below is a GIF showcasing the Dashboard built by me using Plotly Dash. I have taken inspiration from the Aarogya Setu app as I don’t think I have the design acumen. Also, I feel the app does a pretty good job of articulating the data insights.
The steps that went into the whole process of developing and setting up the dashboard for everyone to see, broadly are
Figuring out the Datasource 💽Creating a Static Dashboard 📊Making it Interactive 💹Containerizing Everything 📦Deploying the Project 🖥️
Figuring out the Datasource 💽
Creating a Static Dashboard 📊
Making it Interactive 💹
Containerizing Everything 📦
Deploying the Project 🖥️
Now, I will be elaborating on each of the points.
I would recommend to always create a separate environment for all your Python projects. It makes it easy as you don’t face any dependency issues and also it helps a lot in deployment. Anaconda is my go-to tool for the same.
This is one task that can be as simple as using a CSV file downloaded from Kaggle or any other data platform or as difficult as scraping a large dataset off of a website.
The dataset I’m using for my dashboard is coming from this API. There are multiple APIs and one can use these as per their needs. The only thing to keep in mind is that although all the historical data is present, the data is refreshed daily for the present day. So, this is one thing you need to take care of when designing your data source: That the new data should get added daily.
Now that the data source is figured out, you need a way to store the data. It can be anything such as CSV, SQL table, e.t.c. As the data is not much and to keep everything simple I have used CSV files as my database and the logic for adding and updating records can be found here.
For building static web pages one definitely needs to know HTML and CSS, but with Plotly Dash it's exactly not the case. Dash is a web application framework that adds pure Python abstraction over HTML, CSS, and javascript. Having said that, one can learn the basics of HTML and CSS through W3 schools. It's super basic! (At least for creating a dashboard like mine 😛)
Note: For the CSS changes to show, make sure to save your CSS file in the folder path ./assets/typography.css (Here ‘.’ represents the main project folder). The naming has to be just like this only. Also, you can use the HTML tag, id or class to reference the component in the app.py file directly.
Dash provides us with a lot of functionalities out of the box but I won’t be covering all of them. Following are the ones used by me:-
Dash HTML components: Instead of writing HTML or using an HTML templating engine, you compose your layout using Python structures with the dash-html-components library. It provides all the HTML tags.
Dash Core components: Dash ships with supercharged components for interactive user interfaces. A core set of components, written and maintained by the Dash team, is available in the dash-core-components library.
Dash DAQ: Dash DAQ comprises a robust set of controls that make it simpler to integrate data acquisition and controls into your Dash applications.
The basic app layout can be easily found on the tutorials. Below, I will try to explain each and every component of my dashboard and how did I come up with it.
2.1 The Top Section
This section contains the title along with some of my advertising(LOL) followed by showing the total metrics to date and their jump from the previous day. This section will definitely change on a daily basis but still, we can create its static version. In the layout.py file above, lines 13–39make up this section.
Note: For the images to show up in your dashboard, they should be stored inside the path ./assets/ . Kindly pay attention to the spelling of the folder ‘assets’. The subfolders can be named anything.
If you see carefully, the HTML tag <h1>COVID19 India Dashboard</h1> changes to html.h1(‘COVID19 India Dashboard’). The HTML tag attributes can be sent using parameters to dash HTML components.
Another example <img src=’/assets/images/kaggle.png’ class=’img’> is equivalent to html.Img(src=’/assets/images/kaggle.png’,className=’img’)
The function(below) shows the function that was used to create a table(using dash HTML components) from pandas dataframe.
2.2 The Middle Section
This is the heart of the dashboard containing the dropdown menu, the tabs(active, confirmed, recovered & deceased), the graph(line+bar), and the toggle switch. Lines 40–64 make up the middle section in the layout.py file shown above.
dropdown is pretty easy to add and here are a lot of examples for you to refer to. It’s a part of dash-core-components.
tabs are added using this documentation. It’s a part of dash-core-components.
graph, which is too a part of dash-core-components, can be added using this. dcc.graph() should contain a plotly figure object. A plotly figure object can be created using plotly express or graph objects. plotly express is very easy to use API while graph objects is a bit non-trivial but provides a lot of customization.
ToggleSwitch, which is a part of dash daq, can be added referring to this link.
2.3 The Bottom Section
Lines 65–70 make up this section and it contains the heading along with a table showing the state-wise breakdown. The table will be dynamic(as the position of states can change depending on the total cases), so I have created a function that creates a table that can be shown using dash-html-components from a pandas dataframe. The function is almost similar to the one used for the 2.1 section. It is by the name generate_table() in the code.
Usually, JavaScript is needed to make websites interactive, but don’t worry we don't need to know it for creating dashboards using plotly dash. You just need to know Python!
Dash provides callback functions, which are nothing but Python Decorators that are automatically called by Dash whenever an input component’s property changes. Refer to this Youtube Video to learn more about Decorators.
If you have seen my dashboard or even the GIF at the top, you can make out that all the interactivity involved is in the graph:-
Change based on the state selected in the dropdown. By default, it shows data for India as a whole.
Change based on the tab selected: Active, Confirmed, Recovered, or Deceased.
On hover, show values along with the date on the top-left corner.
Change based on the toggle switch: Cumulative(Line graph) or Daily(Bar graph).
All the changes take place in the same graph only, so we would require only a single callback function. I’ll try to explain it below in simple words.
state-dropdown is the “id” of the dropdown and we are getting the value of its “value” parameter as 1st input. The default value is India.india-graph is the “id” of the graph itself, but here we are getting the value of its “hoverData” parameter as the 2nd input. The default value is Null. (As we are not hovering over the graph once we open the app.)my-toggle-switch is the “id” of the ToggleSwitch and we are getting the value of its “value” parameter as the 3rd input. The default value is True that I assume is Cumulative.tabs is the “id” of the Tabs component and we are getting the value of its “value” parameter as the 4th input. The default value is Active.
state-dropdown is the “id” of the dropdown and we are getting the value of its “value” parameter as 1st input. The default value is India.
india-graph is the “id” of the graph itself, but here we are getting the value of its “hoverData” parameter as the 2nd input. The default value is Null. (As we are not hovering over the graph once we open the app.)
my-toggle-switch is the “id” of the ToggleSwitch and we are getting the value of its “value” parameter as the 3rd input. The default value is True that I assume is Cumulative.
tabs is the “id” of the Tabs component and we are getting the value of its “value” parameter as the 4th input. The default value is Active.
The output of the callback is a graph whose “id” is india-graph and the output is sent to the graph’s figure parameter. (I would request you to refer to plotly graph objects documentation in case you find any problem in understanding it.)
So, once you open the app you will be seeing Cumulative(3) Active(4) COVID19 Cases for India(1) without any hoverinfo(2) as per the callback function parameters. The number within the parenthesis shows the Input order sent to the callback function.
The Input & Output you see in the callback function are the dash dependencies. If these are multiple then they are required to be sent as a list (4 Inputs in the above example). Just keep in mind you need to send these to the decorator/callback function and below you can define a function with any name and give them any parameter names you like.
The function update_tab_graph takes in the 4 Inputs defined in the callback:(One can think of these parameters as mappings to the callback inputs)
state = value in Input 1.hdata = hoverData in Input 2.r_value = value in Input 3.col = value in Input 4.
state = value in Input 1.
hdata = hoverData in Input 2.
r_value = value in Input 3.
col = value in Input 4.
Output is the figure object returned by the function.
Now, if someone changes anything among the 4 inputs, the callback will be triggered and the graph will be updated. Like the figure above shows an example for Delhi.
Docker is an amazing tool for creating containers and it is pretty easy to use. The best part is that the containers are OS agnostic. Most of the containers are Linux-based but can run on Windows/Mac OS without any issues thanks to some awesome technology that’s out of the scope of this article.
Docker in itself is huge and can’t be explained in this article for sure. So, I will just try to explain it in my own simple words.
Let’s just say you created a Python project. Now you want to share it with your friend. One simple way is to share the entire project folder. Your friend will then create a new environment and install the dependencies in the requirements.txt file and then will be able to run the project. This approach is very easy for seasoned developers but for someone who’s just starting out or even not much aware of the setup process, will surely face a lot of issues. This is where Docker comes to the rescue. Your friend just needs to have Docker installed(Docker Desktop preferred) and then he/she can import your Docker image and then just run it to see your project. Basically, if your docker container runs on your local machine, it will surely run any other machine irrespective of the OS.
To clear out the confusion, you just need to know these 3 things to get started with Docker:
Dockerfile: This is the file that contains all the instructions line by line to create your Docker Image.
Image: The entire package/build containing the Dockerfile along with all the required project files(you can ignore some files by mentioning them in the .dockerignore file) and all the dependencies installed.
Container: An instance of an image that is run by following the steps/layers in the Dockerfile sequentially.
An amazing analogy I read somewhere: A Container is a cookie, an image is the mould used to create that cookie and a Dockerfile are the instructions that went into creating that mould.
Below is the Dockerfile that I used for my project. I’ll try to explain all the steps/layers one by one.
FROM python:3.8-slimWORKDIR /app COPY . . RUN pip install -r requirements.txt EXPOSE 8050 CMD [“python”, “app.py”]
FROM python:3.8-slim imports the python image (basically, python3.8 installed on Linux OS). I have imported the slim version as I wanted to keep my image lightweight.
WORKDIR /app creates a directory with the name “app” in our python image.
COPY . . copies all the files and folders in the project folder to the app directory. Files/Folders mentioned in the .dockerignore file are ignored.
RUN pip install -r requirements.txt runs the command line that installs all the dependencies inside the requirements.txt file. This file was copied in the previous step.
EXPOSE 8050 exposes the port 8050 on the docker side. You need to be careful while mapping your machine’s port to this.
CMD [“python”, “app.py”] runs your project. It's exactly similar to the command line(just the text split into a list at spaces) you’ll use to run your project in your local machine.
Once, the Dockerfile is completed, execute the below code in the same folder to build your docker image.
docker build -t covid-dashboard-india .
Finally, to run your container execute the code below. Pay attention to the port mapping I have done. It’s done using the -p tag and on the left side of the semicolon is your local machine’s port and on the right side is the container’s port.
docker run -p 8050:8050 covid-dashboard-india
Navigate to your localhost at port 8050 to see the Dashboard and play around with it.
If you are satisfied with everything, then the final step is just choosing a registry where you could deploy your docker image. There are a plethora of registries out there such as Heroku, AWS ECR, e.t.c. The best thing is that Heroku is free of cost and I have used it for this project of mine.
Just follow all the steps mentioned in this link to get your image deployed. It is pretty easy to follow.
I hope that you find this article useful. Feel free to reach out to me in case of any queries :)