Display Content with pn.panel#

In this guide, we will learn to display Python objects easily with pn.panel:

  • Display any Python object via pn.panel(the_object, ...).

Note

When we ask to run the code in the sections below, we may execute the code directly in the Panel docs via the green run button, in a cell in a notebook, or in a file app.py that is served with panel serve app.py --dev.

import panel as pn
pn.extension("plotly", "vega")

Display a String#

To build an app, our first step is to display things. Luckily, Panel provides us with the simple yet powerful pn.panel() function. This function effortlessly transforms Python objects into viewable components within our app. Let’s start with something simple: a string.

Run the code:

import panel as pn

pn.extension()

pn.panel("Hello World").servable()

Note

We add .servable() to the component to add it to the app served by panel serve app.py --dev. Adding .servable() is not needed to display the component in a notebook.

pn.panel uses a heuristic algorithm to determine how to best display the object. To make this very explicit, we will print the component in all the examples below.

Run the code:

import panel as pn

pn.extension()

component = pn.panel("Hello World")
print(component)

component.servable()
Markdown(str)

Your cell or terminal output should contain Markdown(str). It means pn.panel has picked a Markdown pane to display the str object.

Let’s verify that markdown strings are actually displayed and rendered nicely.

Run the code:

import panel as pn

pn.extension()

component = pn.panel("""
# Wind Turbine

A wind turbine is a device that converts the kinetic energy of wind into \
[electrical energy](https://en.wikipedia.org/wiki/Electrical_energy).

Read more [here](https://en.wikipedia.org/wiki/Wind_turbine).
""")
print(component)

component.servable()
Markdown(str)

Tip

Markdown rendering is very useful in Panel applications, such as for displaying formatted text, headers, links, images, LaTeX formulas and other rich content

Display a DataFrame#

Now that we’ve mastered the art of displaying strings, let’s take it up a notch. In our journey to build a data-centric app, we’ll often need to display more complex objects like dataframes. With Panel, it’s as easy as pie.

Run the code:

import pandas as pd
import panel as pn

pn.extension()

data = pd.DataFrame([
    ('Monday', 7), ('Tuesday', 4), ('Wednesday', 9), ('Thursday', 4),
    ('Friday', 4), ('Saturday', 5), ('Sunday', 4)], columns=['Day', 'Wind Speed (m/s)']
)
component = pn.panel(data)
print(component)
component.servable()
DataFrame(DataFrame)

Tip

If we want to display larger dataframes, customize the way the dataframes are displayed, or make them more interactive, we can find specialized components in the Component Gallery supporting these use cases. For example, the Tabulator widget and Perspective pane.

Display Plots#

Many data apps contains one or more plots. Lets try to display some.

Pick a plotting library below.

Run the code below:

import altair as alt
import pandas as pd
import panel as pn

pn.extension("vega")

data = pd.DataFrame([
    ('Monday', 7), ('Tuesday', 4), ('Wednesday', 9), ('Thursday', 4),
    ('Friday', 4), ('Saturday', 5), ('Sunday', 4)], columns=['Day', 'Wind Speed (m/s)']
)

fig = (
    alt.Chart(data)
    .mark_line(point=True)
    .encode(
        x="Day",
        y=alt.Y("Wind Speed (m/s)", scale=alt.Scale(domain=(0, 10))),
        tooltip=["Day", "Wind Speed (m/s)"],
    )
    .properties(width="container", height="container", title="Wind Speed Over the Week")
)

component = pn.panel(fig, sizing_mode="stretch_width", height=400)
print(component)

component.servable()
Vega(Chart, height=400, selection=Selection, sizing_mode='stretch_width')

Please notice that pn.panel chose a Vega pane to display the Altair figure.

Note

Vega is the name of the JavaScript plotting library used by Altair.

We must add "vega" as an argument to pn.extension in the example to load the Vega Javascript dependencies in the browser.

If we forget to add "vega" to pn.extension, then the Altair figure might not display.

Run the code below:

import hvplot.pandas
import numpy as np
import pandas as pd
import panel as pn

pn.extension()

data = pd.DataFrame([
    ('Monday', 7), ('Tuesday', 4), ('Wednesday', 9), ('Thursday', 4),
    ('Friday', 4), ('Saturday', 5), ('Sunday', 4)], columns=['Day', 'Wind Speed (m/s)']
)

fig = data.hvplot(x="Day", y="Wind Speed (m/s)", line_width=10, ylim=(0,10))

component = pn.panel(fig, sizing_mode="stretch_width", )
print(component)

component.servable()
HoloViews(Curve, sizing_mode='stretch_width')

Please notice that pn.panel chose a HoloViews pane to display the hvPlot figure.

Note

hvPlot is the easy to use plotting sister of Panel. It works similarly to the familiar Pandas .plot API. hvPlot is built on top of the data visualization library HoloViews. hvPlot, HoloViews, and Panel are all part of the HoloViz family.

Run the code below:

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import panel as pn

matplotlib.use("agg")

pn.extension()

data = pd.DataFrame([
    ('Monday', 7), ('Tuesday', 4), ('Wednesday', 9), ('Thursday', 4),
    ('Friday', 4), ('Saturday', 5), ('Sunday', 4)], columns=['Day', 'Wind Speed (m/s)']
)

fig, ax = plt.subplots(figsize=(8,3))
ax.plot(
    data["Day"], data["Wind Speed (m/s)"], marker="o", markersize=10, linewidth=4
)
ax.set(
    xlabel="Day",
    ylabel="Wind Speed (m/s)",
    title="Wind Speed Over the Week",
    ylim=(0, 10),
)
ax.grid()
plt.close(fig)  # CLOSE THE FIGURE TO AVOID MEMORY LEAKS!

component = pn.panel(
    fig, format="svg", dpi=144, tight=True, sizing_mode="stretch_width"
)
print(component)

component.servable()
Matplotlib(Figure, format='svg', sizing_mode='stretch_width', tight=True)

Please notice pn.panel chose a Matplotlib pane to display the Matplotlib figure.

Note

In the example above we provided arguments to pn.panel. These will be applied to the pane selected by pn.panel to display the object. In this example the Matplotlib pane is selected.

The arguments dpi, format and tight would not make sense if a string was provided as an argument to pn.panel. In that case, pn.panel would pick a Markdown pane and the exception TypeError: Markdown.__init__() got an unexpected keyword argument 'dpi' would be raised.

import pandas as pd
import panel as pn
import plotly.express as px

pn.extension("plotly")

data = pd.DataFrame([
    ('Monday', 7), ('Tuesday', 4), ('Wednesday', 9), ('Thursday', 4),
    ('Friday', 4), ('Saturday', 5), ('Sunday', 4)], columns=['Day', 'Wind Speed (m/s)']
)

fig = px.line(data, x="Day", y="Wind Speed (m/s)")
fig.update_traces(mode="lines+markers", marker=dict(size=10), line=dict(width=4))
fig.update_yaxes(range=[0, max(data['Wind Speed (m/s)']) + 1])
fig.layout.autosize = True

component = pn.panel(fig, height=400, sizing_mode="stretch_width")
print(component)

component.servable()
Plotly(Figure, height=400, sizing_mode='stretch_width')

Please notice that pn.panel chose a Plotly pane to display the Plotly figure.

Note

We must add "plotly" as an argument to pn.extension in the example to load the Plotly Javascript dependencies in the browser.

If we forget to add "plotly" to pn.extension, then the Plotly figure might not display.

Display any Python object#

pn.panel can display (almost) any Python object.

Run the code below:

import panel as pn

pn.extension()

component = pn.Column(
    pn.panel({"Wind Speeds": [0, 3, 6, 9, 12, 15, 18, 21], "Power Output": [0,39,260,780, 1300, 1300, 0, 0]}),
    pn.panel("https://assets.holoviz.org/panel/tutorials/wind_turbine.png", height=100),
    pn.panel("https://assets.holoviz.org/panel/tutorials/wind_turbine.mp3"),
)
print(component)

component.servable()
Column
    [0] JSON(dict)
    [1] PNG(str, height=100)
    [2] Audio(str)

Display any Python object in a layout#

If we place objects in a layout like pn.Column (more about layouts later), then the layout will apply pn.panel for us automatically.

Run the code below:

import panel as pn

pn.extension()

component = pn.Column(
    {"Wind Speeds": [0, 3, 6, 9, 12, 15, 18, 21], "Power Output": [0,39,260,780, 1300, 1300, 0, 0]},
    "https://assets.holoviz.org/panel/tutorials/wind_turbine.png",
    "https://assets.holoviz.org/panel/tutorials/wind_turbine.mp3",
)
print(component)

component.servable()
Column
    [0] JSON(dict)
    [1] PNG(str)
    [2] Audio(str)

Please notice that the image of the wind turbine is quite large. To fine-tune the way it is displayed, we can use pn.panel with arguments.

Run the code below:

import panel as pn

pn.extension()

component = pn.Column(
    pn.panel({"Wind Speeds": [0, 3, 6, 9, 12, 15, 18, 21], "Power Output": [0,39,260,780, 1300, 1300, 0, 0]}),
    pn.panel("https://assets.holoviz.org/panel/tutorials/wind_turbine.png", height=100),
    pn.panel("https://assets.holoviz.org/panel/tutorials/wind_turbine.mp3", styles={"background": "orange", "padding": "10px"}),
)
print(component)

component.servable()
Column
    [0] JSON(dict)
    [1] PNG(str, height=100)
    [2] Audio(str, styles={'background': 'orange', ...})

Note

The example above sets the css styles of the Audio player. The styles parameter is introduced in the Styles tutorial.

Consider Performance#

pn.panel is a versatile helper function that converts objects into a Pane. It automatically selects the best representation for an object based on available Pane types, ranking them by priority.

For optimal performance, specify the desired Pane type directly, like pn.pane.Matplotlib(fig) instead of using pn.panel(fig). You will learn about Panes in the Display Content with Panes section.

Recap#

In this guide, we have learned to display Python objects easily with pn.panel:

  • Display a string with pn.panel(some_string)

  • Display plot figures like Altair, hvPlot, Matplotlib and Plotly with pn.panel(fig)

  • Display DataFrames with pn.panel(df)

  • Display most Python objects with pn.panel(some_python_object)

  • Configure how an object is displayed by giving arguments to pn.panel

  • Display most Python objects in layouts like pn.Column with and without the use of pn.panel

  • Use a specific Pane instead of pn.panel if performance is key

  • Add JavaScript dependencies via pn.extension. For example pn.extension("vega") or pn.extension("plotly")

Resources#

Tutorials#

How-to#