{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "\n",
    "import pandas as pd\n",
    "import holoviews as hv\n",
    "\n",
    "from sklearn.cluster import KMeans\n",
    "\n",
    "penguins = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv')\n",
    "cols = list(penguins.columns)[:-1]\n",
    "\n",
    "pn.extension('ace')\n",
    "\n",
    "import hvplot.pandas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [],
   "source": [
    "slider = pn.widgets.IntSlider(start=0, end=10)\n",
    "\n",
    "img = pn.pane.JPG(f\"https://picsum.photos/800/300?image=0\", embed=False, height=300)\n",
    "\n",
    "slider.jscallback(args={'img': img}, value=\"\"\"\n",
    "img.text = '<img src=\"https://picsum.photos/800/300?image='+cb_obj.value+'\" width=800 height=300></img>'\n",
    "\"\"\")\n",
    "\n",
    "app = pn.Column(slider, img)\n",
    "\n",
    "ace = pn.widgets.Ace(readonly=True, width=800, height=200, language='python', theme='monokai', value=\\\n",
    "\"\"\"slider = pn.widgets.IntSlider(start=0, end=10)\n",
    "\n",
    "def slideshow(index):\n",
    "    url = f\"https://picsum.photos/800/300?image={index}\"\n",
    "    return pn.pane.JPG(url)\n",
    "\n",
    "output = pn.bind(slideshow, slider)\n",
    "\n",
    "app = pn.Column(slider, output)\"\"\")\n",
    "\n",
    "app1 = pn.Tabs(('Output', app), ('Code', ace))\n",
    "\n",
    "penguins = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv').dropna()\n",
    "cols = list(penguins.columns)[2:6]\n",
    "\n",
    "x = pn.widgets.Select(name='x', options=cols)\n",
    "y = pn.widgets.Select(name='y', options=cols, value='bill_depth_mm')\n",
    "n_clusters = pn.widgets.IntSlider(name='n_clusters', start=2, end=5, value=3)\n",
    "\n",
    "def cluster(data, n_clusters):\n",
    "    kmeans = KMeans(n_clusters=n_clusters)\n",
    "    est = kmeans.fit(data)\n",
    "    return est.labels_.astype('str')\n",
    "\n",
    "def plot(x, y, n_clusters):\n",
    "    penguins['labels'] = cluster(penguins.iloc[:, 2:6].values, n_clusters)\n",
    "    centers = penguins.groupby('labels').mean()\n",
    "    return (penguins.sort_values('labels').hvplot.scatter(\n",
    "        x, y, c='labels', hover_cols=['species'], line_width=1, size=60, frame_width=400, frame_height=400\n",
    "    ).opts(marker=hv.dim('species').categorize({'Adelie': 'square', 'Chinstrap': 'circle', 'Gentoo': 'triangle'})) * centers.hvplot.scatter(\n",
    "        x, y, marker='x', color='black', size=400, padding=0.1, line_width=5\n",
    "    ))\n",
    "\n",
    "explanation = pn.pane.Markdown(\"\"\"\n",
    "This app applies k-means clustering on the Palmer Penguins dataset using scikit-learn, parameterizing the number of clusters and the variables to plot.\n",
    "<br><br>\n",
    "Each cluster is denoted by one color while the penguin species is indicated using markers: \n",
    "<br><br>\n",
    "● - Adelie, ▲ - Gentoo, ■ - Chinstrap\n",
    "<br><br>\n",
    "By comparing the two we can assess the performance of the clustering algorithm.\n",
    "<br><br>\n",
    "\"\"\")\n",
    "\n",
    "code = pn.widgets.Ace(language='python', theme='monokai', height=360, value=\\\n",
    "\"\"\"x = pn.widgets.Select(name='x', options=cols)\n",
    "y = pn.widgets.Select(name='y', options=cols, value='bill_depth_mm')\n",
    "n_clusters = pn.widgets.IntSlider(name='n_clusters', start=2, end=5, value=3)\n",
    "explanation = pn.pane.Markdown(...)\n",
    "\n",
    "def plot_clusters(x, y, n_clusters):\n",
    "    ...\n",
    "    \n",
    "pn.Row(\n",
    "    pn.WidgetBox(x, y, n_clusters, explanation),  \n",
    "    pn.bind(plot, x, y, n_clusters)\n",
    ")\"\"\", width=800)\n",
    "\n",
    "app2 = pn.Tabs(\n",
    "    ('Output', pn.Column(\n",
    "        pn.Row(\n",
    "            pn.WidgetBox(x, y, n_clusters, explanation),  \n",
    "            pn.bind(plot, x, y, n_clusters)\n",
    "        )\n",
    "    )),\n",
    "    ('Code', code)\n",
    ")\n",
    "\n",
    "pn.Row(pn.layout.HSpacer(), pn.Tabs(\n",
    "  ('Penguin K-Means Clustering', app2),\n",
    "  ('Slideshow', app1)\n",
    "), pn.layout.HSpacer(), sizing_mode='stretch_width').embed(max_opts=4, json=True, json_prefix='json')"
   ]
  }
 ],
 "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.7.10"
  },
  "toc-autonumbering": false,
  "toc-showcode": true,
  "toc-showmarkdowntxt": true,
  "toc-showtags": true,
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
