import panel as pn
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
from xgboost import XGBClassifier
iris_df = load_iris(as_frame=True)
trees = pn.widgets.IntSlider(start=2, end=30, name="Number of trees")
def pipeline(trees):
model = XGBClassifier(max_depth=2, n_estimators=trees)
model.fit(iris_df.data, iris_df.target)
accuracy = round(accuracy_score(iris_df.target, model.predict(iris_df.data)) * 100, 1)
return pn.indicators.Number(
name="Training accuracy",
value=accuracy,
format="{value}%",
colors=[(97.5, "red"), (99.0, "orange"), (100, "green")],
)
pn.Column(
"Simple example of training an XGBoost classification model on the small Iris dataset.",
iris_df.data.head(),
"Move the slider below to change the number of training rounds for the XGBoost classifier. The training accuracy score will adjust accordingly.",
trees,
pn.bind(pipeline, trees),
).servable()Panel, from the HoloViz project, turns Python functions into web apps and dashboards. You connect widgets such as sliders, dropdowns and buttons to a function, and Panel runs the function again each time a widget changes. It can show pandas tables, Matplotlib, Bokeh and Plotly charts, and HoloViews plots. People use it for data exploration tools, model demos and internal dashboards. This page is an online Panel compiler: the code runs in your browser, so you can try it without installing anything. Run the example first, then paste any snippet below into a new cell to try it.
load_iris(as_frame=True) loads scikit-learn's built-in Iris dataset: 150
flowers, four measurements each and three species.
pn.widgets.IntSlider makes a slider from 2 to 30 that starts at 2.
pipeline() trains an XGBoost classifier with
n_estimators set to the slider value, scores it on the data it trained
on, and returns the accuracy as a pn.indicators.Number. The colors
list shows the number in red up to 97.5%, orange up to 99% and green
above that. pn.bind(pipeline, trees) calls pipeline() with the
slider's value and calls it again whenever the slider moves. pn.Column
stacks the text, the first five rows of data, the slider and the result,
and .servable() marks the column as the app, which appears below the
cell when it runs.
n_estimators counts boosting rounds: with three species, XGBoost adds
three trees per round. Two rounds score 97.3%, and 27 or more score 100%.
A perfect score on the training data does not show how the model does on
flowers it has not seen.
pn.bind() takes several widgets. Each widget's value goes to the
matching argument, and a change to any of them runs the function again:
import pandas as pd
import panel as pn
sales = pd.DataFrame({
"region": ["North", "South", "North", "East", "South", "East", "North"],
"product": ["Tea", "Tea", "Coffee", "Coffee", "Juice", "Tea", "Juice"],
"units": [120, 80, 150, 60, 90, 110, 40],
})
region = pn.widgets.Select(name="Region", options=["All", "North", "South", "East"])
min_units = pn.widgets.IntSlider(name="Minimum units", start=0, end=150, step=10)
def filter_rows(region, min_units):
rows = sales[sales["units"] >= min_units]
if region != "All":
rows = rows[rows["region"] == region]
return pn.pane.DataFrame(rows, index=False)
pn.Column(region, min_units, pn.bind(filter_rows, region, min_units)).servable()
Wrap the figure in pn.pane.Matplotlib. Build it with
matplotlib.figure.Figure rather than plt.subplots(): pyplot keeps
every figure it creates open, and this function runs on every slider
move.
import numpy as np
import panel as pn
from matplotlib.figure import Figure
freq = pn.widgets.FloatSlider(name="Frequency", start=0.5, end=5, step=0.5, value=1)
def plot(freq):
x = np.linspace(0, 2 * np.pi, 200)
fig = Figure(figsize=(6, 3))
ax = fig.subplots()
ax.plot(x, np.sin(freq * x))
ax.set_title(f"sin({freq}x)")
return pn.pane.Matplotlib(fig, dpi=96, tight=True)
pn.Column(freq, pn.bind(plot, freq)).servable()
on_click() registers a function that runs on every click and receives
the click event. Setting a pane's object replaces what it shows:
import panel as pn
task = pn.widgets.TextInput(name="Task", placeholder="Type a task")
add = pn.widgets.Button(name="Add", button_type="primary")
tasks = pn.pane.Markdown("No tasks yet.")
items = []
def add_task(event):
if task.value:
items.append(task.value)
tasks.object = "\n".join(f"- {item}" for item in items)
task.value = ""
add.on_click(add_task)
pn.Column(pn.Row(task, add), tasks).servable()
For HoloViews plots driven by dropdowns, see HoloViews + Panel.
.servable(). A Panel object left on the last line,
the way Jupyter shows one, displays an error here instead of the app.
.show() and pn.serve() start a web server, so they fail with
RuntimeError: Cannot serve application in pyodide context.