The world’s leading publication for data science, AI, and ML professionals.

Using Panel to Build Data Dashboards in Python

Let's build an interactive data dashboard using Panel from Holoviz

Photo by path digital on Unsplash
Photo by path digital on Unsplash

Holoviz is quickly becoming a popular set of Python plotting libraries for beginners and veterans alike. Holoviz consists of several packages with the goal of making it easier to visualize Data regardless of the data type, all while improving the quality of your plots. Some of these libraries include hvPlot, Panel, HoloViews, and GeoViews.

In this post, we will be learning how to use Panel to create interactive data dashboards and web apps. Panel has quickly become one of my favorite dashboarding tools because it is easy to learn the basics, while still having plenty of depth to later create more complex apps. It also is very flexible with the type of plot you can use, which means that if you have already created a map using Folium, you don’t have to spend time rebuilding it with another tool to integrate it into a dashboard.

Why Dashboards?

Data dashboarding isn’t a new practice; businesses have used dashboards to track and understand their data for many years. Dashboards have often been built with JavaScript or no-code software, however, with new libraries like Panel, it’s never been easier to create a dashboard using Python. Having the option to use the same language for your entire workflow can help save a lot of time, especially when you are prototyping.

Dashboards provide several key benefits like interactivity, customizability, and shareability. Since we can define widgets, like a slider to change the year of a time series, we can have meaningful interaction that helps the user see changes in the data.

Being able to customize the layout also allows mixing different kinds of plots or using multiple plots to display various dimensions of a dataset. Finally, shareability. Panel makes it easy to deploy a dashboard as a web app, which means you can quickly share your work with larger audiences online.

Materials

We create several interactive plots in this post, however, they can’t be easily embedded into Medium directly, so you can follow along with this interactive Jupyter notebook.

Panel Introduction

Before we dive into creating our first dashboard using Panel, let’s first quickly discuss the basics of how it works.

Components

An app made with Panel consists of three primary components:

  • Pane: A Pane is a rendered view of your plot. Your plot can be an object created with many popular Python plotting libraries. A Pane is essentially just converting your existing plot into an object Panel can work with.
  • Widget: Widgets allow for user input like clicking or entering data, allowing user interaction with an app.
  • Panel: A Panel is a container that holds the Panes and Widgets that make up your app. Panels are hierarchical, which means there can be Panels inside of Panels. Panels can also organize elements into rows and columns, tabs, or a grid.

These three objects are the essential building blocks of a Panel dashboard. We convert our plots into Panes, create widgets to control variables, and then organize it all into a Panel – or group of Panels.

APIs

One of Panel’s major advantages is how flexible it can be. We can use Panel to create a quick dashboard in 15 minutes, and if the concept works, we can continue customizing our dashboard and even integrate it into a larger software project without having to start over with a new tool.

Panel is able to provide quick drafting and more complex capabilities by giving you the option of four different APIs. In this post, we will focus on two of them: Interact functions and Reactive functions.

Interact API

Interact functions are the easiest way to begin building interactive dashboards. You simply provide a function and then Panel generates the UI needed to interact with it. We can create a simple Interact function with Panel inside of our Jupyter notebook like this:

Created By Author
Created By Author

Here we create a simple function that returns the product of a number, and then we tell Panel that we want to interact with the function. The value of x now changes based on the slider, and we can use x as a parameter to functions to make them responsive to our interaction.

Reactive Functions

What makes Interact functions so simple is that they create the UI elements for us, like the slider in the example above. Reactive functions allow us to build our UI elements and functions separately and decide how to link them.

We can make a quick example plot using the popular Palmer Penguins data set like this:

Created By Author
Created By Author

There are three steps here:

  1. Declare our two selection widgets, which will let us choose any of our columns to be the x or y-axis.
  2. Use nested rows and columns,pn.Row(pn.Column(<TITLE AND WIDGETS>), <PLOT>) , to organize our content into a single row but separate it into two columns.
  3. Use pn.bind() to connect our scatter plot with our two widgets and then Panel handles the rest for us.

Declaring the widgets separately from the plot gives us a lot more control over the styling and organization of our UI elements, and the only downside compared to using Interact functions is having to write some extra code. I really like that Reactive functions are more declarative, which makes it very clear what each element is meant to do.


Creating a Dashboard with Panel

The data set we will be working with in this post consists of information about Data Science jobs worldwide from 2020–2022. There are about 600 jobs in the data set, which makes it a good size for an example that won’t be too difficult for a browser to load regardless of the kinds of plots we decide to make.

Let’s import the data into Python and see what we are working with.

Created By Author
Created By Author

We can see that we have information like an employee’s experience level, salary, remote work ratio, and the locations of the company and the employee. There are quite a few interesting plots we can make from this, so let’s create a few to explore the data and then populate our dashboard.

Basic Plots

Medium doesn’t support uploading HTML directly, so the plots here in the post aren’t interactive. If you would like to interact with the plots, you can follow along with this interactive notebook.

Let’s start by importing the hvplot pandas library and setting the holoviews extension to bokeh. I’ve been a long-time fan of Plotly, which is also an option for the holoviews extension, but I have been really enjoying bokeh’s default styling.

Let’s start by making a simple box plot to look at the distribution of salary depending on experience level.

Created By Author
Created By Author

Here we can see how hvPlot takes the place of the DataFrame’s normal plotting functionality. Now, for the rest of the plots, I want to be able to subset the data by year, so we’ll use functions that take the year as a parameter. Our next plot will be a bar plot looking at the mean salary by experience level.

Created By Author
Created By Author

Now we can call plot_bars1(2021) to subset the data to only jobs from that year. You can probably see where I am going with this…

Now that we have a function that takes the year as a parameter and returns a plot, we are ready to hook it up to a slider to control the year for us. Why run the function manually with different inputs when we can create a simple UI with Panel?

Year Slider

We will create our year slider much like the selection menus from the Reactive function demo, just with a different type of widget. We can also create a simple function to display the year in markdown so that we can see how to link the slider’s value to a function’s inputs.

There are two primary ways to link a value of a widget to a function, either the pn.bind() method we saw above or the @pn.depends() decorator that we see in this example. Either works, but I do like how the decorator declares the dependency right away rather than waiting until laying out the dashboard.

Now in a Jupyter notebook, we can render these and see how the slider’s value changes the input value to our function displaying the markdown.

Created By Author
Created By Author

In case you are wondering, value_throttled just tells Panel not to re-run the function until you release your mouse; this prevents it from running multiple times when you move the slider over a few notches.

Final Plots!

We have our infrastructure, now we just need to make a couple more plots to populate our dashboard and hook them up to our slider. Let’s see which countries have the highest average salaries for a given year.

Created By Author
Created By Author

I know the color scheme isn’t great, but I wanted to assign a unique color to each of the nearly 60 countries so that colors weren’t repeated for different countries when the year changes.

You may have noticed that this is finding the average salary based on the country the employee lives in, but what about company location? I also made a function to do nearly the same task, except using company location instead.

Created By Author
Created By Author

Panel Layout

Now we are ready to put it all together. Panel supports multiple ways to arrange objects. In this example, we will use rows and columns since it’s the most intuitive to start with. We can nest as many rows and columns inside of each other as we want.

We will use a WidgetBox as our container, which is basically just a Column but with a little extra styling to make the items inside more visibly grouped together. I also used pn.bind() to show what it would look like to attach the year slider to each plot.

Created By Author
Created By Author

And we finally have a functioning dashboard right in our Jupyter notebook! You can probably see how quickly you could create an interactive dashboard using Panel once you have a handle on these three basic steps – create a plotting function, define a widget, and define a layout.

Of course, dashboards can get significantly more complex than this, however, something as simple as adding a slider for the year of a time-series data set can make a huge difference to the impact of a Data Visualization especially if you want to share it with anyone that doesn’t code.

Serving Dashboards Locally

To host our dashboard locally, all we have to do is run panel serve xxxx.ipynb in the terminal from your working directory. Now you will be able to access it from your browser on localhost .

Wrapping Up

We covered a lot of ground in this post, but I hope the core concepts of how we can use Panel to make interactive dashboards are clear. This post barely scratched the surface of what can be done using Panel and other Holoviz libraries. We can add maps from libraries like Folium, or we can configure a lasso-style selection tool to allow the viewer to subset the data themselves. Luckily Holoviz has excellent documentation and I have a series of posts on Panel coming in the coming weeks.

Resources

Note: If you are enjoying reading my and others’ content here on Medium, consider subscribing using the link below to support the creation of content like this and unlock unlimited stories!

Join Medium with my referral link – Will Norris

Data Citations

Allison Marie Horst. (2020). palmerpenguins: Palmer Archipelago (Antarctica) penguin data. DOI: https://doi.org/10.5281/zenodo.3960218


Related Articles