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 ofpn.panel
Use a specific Pane instead of
pn.panel
if performance is keyAdd JavaScript dependencies via
pn.extension
. For examplepn.extension("vega")
orpn.extension("plotly")