{ "cells": [ { "cell_type": "markdown", "id": "040c997b", "metadata": {}, "source": [ "# The Easiest Way to Create an Interactive Dashboard in Python\n", "\n", "This notebook is an updated version of the original notebook supporting the blog post\n", "\n", "**[The Easiest Way to Create an Interactive Dashboard in Python](https://towardsdatascience.com/the-easiest-way-to-create-an-interactive-dashboard-in-python-77440f2511d1)**. Turn Pandas pipelines into a\n", "dashboard using [`param.rx`](https://param.holoviz.org/user_guide/Reactive_Expressions.html) and [panel.ReactiveExpr](https://panel.holoviz.org/reference/panes/ReactiveExpr.html).\n", "\n", "by *Sophia Yang* and *Marc Skov Madsen*.\n", "\n", "![Data App](https://github.com/sophiamyang/hvplot_interactive/blob/main/assets/easy-dataframe-dashboards.gif?raw=true)" ] }, { "cell_type": "markdown", "id": "abf60b58", "metadata": {}, "source": [ "## Import and configure packages\n", "\n", "Please note that in **Colab** you will need to `!pip install panel hvplot`. In VS Code notebooks you will need to install `!pip install panel hvplot jupyter_bokeh`." ] }, { "cell_type": "code", "execution_count": null, "id": "5cb553bf", "metadata": {}, "outputs": [], "source": [ "# !pip install panel==1.3.6 hvplot==0.9.1 # colab\n", "# !pip install panel==1.3.6 hvplot==0.9.1 jupyter_bokeh==3.0.7 # vscode" ] }, { "cell_type": "code", "execution_count": null, "id": "0f1112af", "metadata": {}, "outputs": [], "source": [ "import param\n", "import panel as pn\n", "\n", "pn.extension('tabulator', sizing_mode=\"stretch_width\")" ] }, { "cell_type": "code", "execution_count": null, "id": "5adb11a6", "metadata": {}, "outputs": [], "source": [ "import hvplot.pandas\n", "import holoviews as hv\n", "\n", "hv.extension('bokeh')" ] }, { "cell_type": "markdown", "id": "ef4ccd06", "metadata": {}, "source": [ "## Define Color Palette" ] }, { "cell_type": "code", "execution_count": null, "id": "ce8c5f82", "metadata": {}, "outputs": [], "source": [ "PALETTE = [\"#ff6f69\", \"#ffcc5c\", \"#88d8b0\", ]\n", "pn.Row(\n", " pn.layout.HSpacer(height=50, styles={\"background\": PALETTE[0]}),\n", " pn.layout.HSpacer(height=50, styles={\"background\": PALETTE[1]}),\n", " pn.layout.HSpacer(height=50, styles={\"background\": PALETTE[2]}),\n", ")" ] }, { "cell_type": "markdown", "id": "7698a74c", "metadata": {}, "source": [ "## Load Data" ] }, { "cell_type": "code", "execution_count": null, "id": "09d60a44", "metadata": {}, "outputs": [], "source": [ "from bokeh.sampledata.autompg import autompg_clean as df\n", "df.head(3)" ] }, { "cell_type": "markdown", "id": "1bfed521", "metadata": {}, "source": [ "## Define DataFrame Pipeline" ] }, { "cell_type": "code", "execution_count": null, "id": "4a42b6e5", "metadata": {}, "outputs": [], "source": [ "def get_data(df, cylinders=4, mfr=['ford','chevrolet'], yaxis=\"hp\"):\n", " return (\n", " df[\n", " (df.cyl == cylinders) & \n", " (df.mfr.isin(mfr))\n", " ]\n", " .groupby(['origin', 'mpg'])[yaxis].mean()\n", " .to_frame()\n", " .reset_index()\n", " .sort_values(by='mpg')\n", " )\n", "\n", "get_data(df).head(3)" ] }, { "cell_type": "markdown", "id": "f928f0ba", "metadata": {}, "source": [ "## Make DataFrame Pipeline Interactive" ] }, { "cell_type": "markdown", "id": "835b20da", "metadata": {}, "source": [ "Define [Panel widgets](https://panel.holoviz.org/reference/index.html#widgets)" ] }, { "cell_type": "code", "execution_count": null, "id": "956fa985", "metadata": {}, "outputs": [], "source": [ "cylinders = pn.widgets.IntSlider(name='Cylinders', start=4, end=8, step=2)\n", "mfr = pn.widgets.ToggleGroup(\n", " name='MFR',\n", " options=['ford', 'chevrolet', 'honda', 'toyota', 'audi'], \n", " value=['ford', 'chevrolet', 'honda', 'toyota', 'audi'],\n", " button_type='primary', button_style=\"outline\")\n", "yaxis = pn.widgets.RadioButtonGroup(\n", " name='Y axis', \n", " options=['hp', 'weight'],\n", " button_type='primary', button_style=\"outline\"\n", ")" ] }, { "cell_type": "markdown", "id": "743aa619", "metadata": {}, "source": [ "Combine pipeline and widgets" ] }, { "cell_type": "code", "execution_count": null, "id": "b8883956", "metadata": {}, "outputs": [], "source": [ "ipipeline=param.rx(get_data)(df, cylinders, mfr, yaxis)\n", "\n", "ipipeline.head()" ] }, { "cell_type": "markdown", "id": "bff77abf", "metadata": {}, "source": [ "## Pipe to Tabulator" ] }, { "cell_type": "code", "execution_count": null, "id": "d262cb39", "metadata": {}, "outputs": [], "source": [ "itable = pn.widgets.Tabulator(ipipeline, pagination='remote', page_size=10)\n", "itable" ] }, { "cell_type": "markdown", "id": "b21344a1", "metadata": {}, "source": [ "Check out the [Tabulator Reference Guide](https://panel.holoviz.org/reference/widgets/Tabulator.html) for more inspiration." ] }, { "cell_type": "markdown", "id": "246398c8", "metadata": {}, "source": [ "## Pipe to hvPlot and HoloViews" ] }, { "cell_type": "markdown", "id": "1fcc805e", "metadata": {}, "source": [ "First we will create the interactive plot with [hvPlot](https://hvplot.holoviz.org/)." ] }, { "cell_type": "code", "execution_count": null, "id": "24423cca", "metadata": {}, "outputs": [], "source": [ "ihvplot = ipipeline.hvplot(x='mpg', y=yaxis, by='origin', color=PALETTE, line_width=6, height=400, responsive=True)\n", "ihvplot" ] }, { "cell_type": "markdown", "id": "a2b5271e", "metadata": {}, "source": [ "The we will put it in a HoloViews pane" ] }, { "cell_type": "code", "execution_count": null, "id": "b958a6e1", "metadata": {}, "outputs": [], "source": [ "iplot = pn.pane.HoloViews(ihvplot)\n", "iplot" ] }, { "cell_type": "markdown", "id": "0c943ca4", "metadata": {}, "source": [ "Check out the [HoloViews Reference Guide](https://panel.holoviz.org/reference/panes/HoloViews.html) for more inspiration" ] }, { "cell_type": "markdown", "id": "345db224", "metadata": {}, "source": [ "## Layout using Template\n", "\n", "Here we use the [FastListTemplate](https://panel.holoviz.org/reference/templates/FastListTemplate.html#templates-gallery-fastlisttemplate)." ] }, { "cell_type": "code", "execution_count": null, "id": "d224e0e7", "metadata": {}, "outputs": [], "source": [ "template = pn.template.FastListTemplate(\n", " title='The easiest way to create a dashboard', \n", " sidebar=[cylinders, 'Manufacturers', mfr, 'Y axis' , yaxis],\n", " main=[iplot, itable],\n", " accent_base_color=\"#88d8b0\",\n", " header_background=\"#88d8b0\",\n", " # main_layout=None, # Use this if you want a gray sidebar and white main area\n", ")\n", "template.servable(); # Add semicolon because templates don't render well in a notebook" ] }, { "cell_type": "markdown", "id": "8831435d", "metadata": {}, "source": [ "To *serve the notebook* run `panel serve the_easiest_way_to_create_dashboard.ipynb`." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.7" } }, "nbformat": 4, "nbformat_minor": 5 }