In this tutorial, I will go through creating a simple and interactive dashboard with Panel. We will use Jupyter Notebook to develop the dashboard and serve it locally.  

What Is Panel?

Panel is an open-source Python library that lets you create custom interactive web apps and dashboards by connecting user-defined widgets to plots, images, tables or text.

 

Basic Interactions in Panel

The easiest way to create interaction between any data set or plot in Panel is to use the interact function. It automatically creates an interactive control and can be a flexible, powerful way to create dashboards.

Let’s see a simple example using Panel interact. Here we create a function that returns the product of a number, and we call Panel to interact on the function.

import panel as pn
def f(x):
  return x * x
pn.interact(f, x=10)

Now, we have an interactive control, where we can drag a slider; the product changes as we change the x values.

Panel’s interact function is easy to use and works well with controls, data tables, visualization or any panel widget. At this high level, you don’t see what’s going on inside, and the dashboard layout's customization requires indexing. However, it’s a clear and robust starting point.

If you want to have more control of your dashboards and customize them entirely, you can either use reactive functions or callbacks in Panel. In our dashboard, what we use depends on a more powerful function.

More on Data Viz From Built In ExpertsForget Bokeh. Use Pygal to Create Data Visualizations Instead.

 

Panel Components

Before we go through creating the dashboard, let’s see the three most essential components in Panel that we’ll use in this dashboard.

Pane 

A pane allows you to display and arrange plots, media, text or any other external objects. You have almost all Python plotting libraries functionality here so that you can use your favorite one (Matplotlib, Bokeh, Vega/Altair, HoloViews, Plotly, Folium, etc.). You can also use markup and embed images with pane.

Widget

Panel provides a consistent and wide range of widgets. You have different types of widgets, including options selectors for single and multiple values (select, radio button, multi-select, etc.) and type based selectors (slider checkbox, dates, text, etc.).

Panel

A panel provides flexible and responsive customization to dashboard layouts. You can have either fixed-size or responsive resizing layouts when you are building dashboards. In Panel, you have four main types:

  • Row :  for horizontal layouts
  • Column :  for vertical layouts
  • Tabs :  selectable tabs layout
  • GridSpec: for grid layout

In the next section, I’ll create a dashboard with interactive controls, data visualizations and a customized dashboard layout.

More From AbdishakurUse Lux and Python to Automatically Create EDA Visualizations

 

Creating a Dashboard With Panel

In this example, we’ll use a global flooding data set ,  Global Active Archive of Large Flood Events , from the flood observatory unit in Dartmouth. Let’s read the data and explore it before we begin constructing the dashboard.

import pandas as pd
import panel as pn

df = pd.read_csv("floods.csv")
df.head()
create-dashboards-panel-python
Global Active Archive of Large Flood Events

In this table, we have coordinates, the time of the flooding and calamities including death and displacement. Also, we have the main cause and severity of the flooding.

 

Sliders

We’ll use range sliders (a widget) for our dashboard to control the range of years when we plot the data visualization.

year = pn.widgets.IntRangeSlider(name='Years Range Slider', width=250, start=1985, end=2016, value=(1985, 2016), value_throttled=(1985, 2016))

This code creates IntRangeSlider between 1985 and 2016. Now we can use this slider to get a value and pass it to a function. So let’s create a simple function that returns a text and the year slider values : value_throttled(start, end).

@pn.depends(year.param.value_throttled)
def year_range(year):
   return '### Floods Between
           {start} --  {end}'.format(start=year[0], end=year[1])

The above function prints out H3 markup text with start and end years depending on the range slider. Note that we’re using depends instead of interact here. With depends we have more control of the parameters.

Before moving on to data visualization and plotting, let’s create another markup for counting the number of deaths in the selected range.

# KPI -- Death
df["Began"] = pd.to_datetime(df["Began"])
df["Ended"] = pd.to_datetime(df["Ended"])
@pn.depends(year.param.value_throttled)
def dead_stat(year):
   return "### Death{}".format(
   df[df.Began.dt.year.between(year[0], year[1])]["Dead"].sum()
   )
pn.Row(dead_stat)

The dead_stat function is similar to the year range. Instead of only returning the year range, the dead_stat function returns the number of deaths between the start and end year selected.

 

Data Visualization Plots

I’ll use the Hvplot library to visualize the data, but you can use any data visualization library of your choice. We’ll create two plots: a bar chart and a map. The logic is the same for both. We’re using the year range slider to control the input and the depends function to create the connection.

# Bar chart
@pn.depends(year.param.value_throttled)
def plot_bar(year):
   years_df = df[df.Began.dt.year.between(year[0], year[1])]
   bar_table = years_df["MainCause"]
    .value_counts()
    .reset_index()
    .rename(columns={"index":'Cause', "MainCause":"Total"})
   return bar_table[:10].sort_values("Total")
    .hvplot.barh("Cause", "Total",
      invert=False, legend='bottom_right', height=600)
# Map
@pn.depends(year.param.value_throttled)
def plot_map(year):
   years_df = df[df.Began.dt.year.between(year[0], year[1])]
   return df.hvplot.points('long', 'lat', xaxis=None, yaxis=None, geo=True, color='red', alpha=0.5, tiles='CartoLight', hover_cols=["Began", "Ended", "Dead", "Displaced"], size=5)

The two functions above return two plots: a bar chart and a map. Let’s display them next and arrange the layout with Panel.

How to Create a Beautiful Python Visualization Dashboard With Panel/Hvplot

 

Panel Layout

I’ll use the simple row and column Panel functions to layout the dashboard. We have different objects in this dashboard, including an image, text and two main plots.

title = '# Worldwide Floods'
logo = pn.panel('floodsImage.png', width=200, align='start')
text = "Dataset:Global Active Archive of Large Flood Events "
# Header box
header_box = pn.WidgetBox(title, logo, year,  pn.layout.Spacer(margin=200), text, width=300, height=1000, align="center")
# Plot Box
plots_box = pn.WidgetBox(pn.Column(pn.Row(pn.Column(year_range), pn.layout.HSpacer(), pn.Column(dead_stat)), plot_map, plot_bar, align="start", width=600,sizing_mode="stretch_width"))
# Dashboard
dashboard = pn.Row(header_box, plots_box, sizing_mode="stretch_width")
dashboard

You can now use your dashboard inside a Jupyter Notebook, and you can serve it locally (refer to Panel documentation if you want to deploy the dashboard on the cloud).

Run the following command to serve the dashboard locally:

panel serve xxxx.ipynb

The following GIF shows how to serve the dashboard locally.

That is it for this tutorial. We have created a simple and interactive dashboard using Panel. In this article, we have gone through the basics of the Panel Python library and used the flood data to create an interactive data visualization dashboard with Python and served the dashboard locally.

With Panel, you can easily customize your dashboards and their superb documentation can help you take your dashboards to the next level.    

Expert Contributors

Built In’s expert contributor network publishes thoughtful, solutions-oriented stories written by innovative tech professionals. It is the tech industry’s definitive destination for sharing compelling, first-person accounts of problem-solving on the road to innovation.

Learn More

Great Companies Need Great People. That's Where We Come In.

Recruit With Us