diff --git a/Dash/Dash_Plotly_Dynamic_Link.ipynb b/Dash/Dash_Plotly_Dynamic_Link.ipynb new file mode 100644 index 0000000000..c73fc36c75 --- /dev/null +++ b/Dash/Dash_Plotly_Dynamic_Link.ipynb @@ -0,0 +1,320 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"Naas\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Dash - Dynamic Link On Plotly Data Label Click" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Tags:** #dash #plotly #naas #analytics" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Author:** [Oguz Akif Tufekcioglu](https://www.linkedin.com/in/oguzakiftufekcioglu/)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook enables you to generate plotly plots with clickable data points that sends to their urls in the dataframe." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Input" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "try:\n", + " import dash\n", + "except:\n", + " !pip install dash --user\n", + " import dash\n", + "try:\n", + " import dash_bootstrap_components as dbc\n", + "except:\n", + " !pip install dash_bootstrap_components --user\n", + " import dash_bootstrap_components as dbc\n", + " \n", + "import webbrowser\n", + "from dash.dependencies import Input, Output\n", + "from dash import html, dcc\n", + "from dash.exceptions import PreventUpdate\n", + "import plotly.express as px\n", + "import plotly.graph_objects as go" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setup Variables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "DASH_PORT = 8050" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize Dash app" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "app = dash.Dash(\n", + " requests_pathname_prefix=f'/user/{os.environ.get(\"JUPYTERHUB_USER\")}/proxy/{DASH_PORT}/', \n", + " external_stylesheets=[dbc.themes.BOOTSTRAP],\n", + " meta_tags=[{'name':'viewport', 'content':'width=device-width, initial-scale=1.0'}]\n", + ") \n", + "\n", + "# if you are not in Naas\n", + "# app = dash.Dash() " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get stock prices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = px.data.stocks() #reading stock price dataset\n", + "print(\"Data fetched:\", len(df))\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add an url column" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# add a url for each stock in the dataset into urls column\n", + "df[\"urls\"] = \"https://www.naas.ai/\"\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create app layout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "app.layout = html.Div(\n", + " id ='parent',\n", + " children=[\n", + " html.H1(\n", + " id='H1',\n", + " children='Dynamic link on label click on plotly chart python',\n", + " style = {\n", + " 'textAlign': 'center',\n", + " 'marginTop': 40,\n", + " 'marginBottom': 40\n", + " }\n", + " ),\n", + " dcc.Graph(\n", + " id='line-plot', \n", + " figure=px.line(\n", + " data_frame=df,\n", + " x='date',\n", + " y='GOOG',\n", + " title='Google stock prices over time',\n", + " hover_name=\"urls\",\n", + " custom_data=(\"urls\",)\n", + " )\n", + " ),\n", + " dcc.Store(\n", + " id='clientside-data',\n", + " data=\"\"\n", + " ),\n", + " dcc.Store(\n", + " id='redirected-url',\n", + " data=\"\"\n", + " ),\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Call callback function to save url in a dcc Store component when data point is clicked" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "@app.callback(Output('clientside-data', 'data'), [Input('line-plot', 'clickData')])\n", + "def open_url(clickData):\n", + " if clickData != None:\n", + " print(clickData)\n", + " url = clickData['points'][0]['customdata'][0]\n", + " return url\n", + " else:\n", + " raise PreventUpdate" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Call client-side callback function open url in a new tab" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "app.clientside_callback(\n", + " \"\"\"\n", + " function(data,scale) {\n", + " console.log(data);\n", + " window.open(data, '_blank');\n", + " return data;\n", + " }\n", + " \"\"\",\n", + " Output(\"redirected-url\", 'data'),\n", + " Input(\"clientside-data\", 'data'),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Output" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generate URL and show logs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "if __name__ == '__main__':\n", + " app.run_server(proxy=f\"http://127.0.0.1:{DASH_PORT}::https://app.naas.ai\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.9.6" + }, + "vscode": { + "interpreter": { + "hash": "1199c261b5e24789861580535954eb82c9d3b7f440249a3a44925e76d155f691" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}