{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vamos agora falar de interação 🕹️\n", "\n", "fonte e material de apoio : https://www.kaggle.com/discussions/getting-started/100831\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Os recursos de visualização podem ser muito bem aproveitados se inserirmos recursos onde o usuário pode interagir com nossa visualização 📊\n", "\n", "### Para isso temos, algumas opções : ipywidgets, D3.js, Bokeh, Plotly , Dash." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/tmp/ipykernel_44521/2402724060.py:2: UserWarning: \n", "The dash_core_components package is deprecated. Please replace\n", "`import dash_core_components as dcc` with `from dash import dcc`\n", " import dash_core_components as dcc\n", "/tmp/ipykernel_44521/2402724060.py:3: UserWarning: \n", "The dash_html_components package is deprecated. Please replace\n", "`import dash_html_components as html` with `from dash import html`\n", " import dash_html_components as html\n" ] } ], "source": [ "import dash\n", "import dash_core_components as dcc\n", "import dash_html_components as html\n", "import plotly.graph_objs as go\n", "import pandas as pd\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "df = pd.read_excel(\"https://github.com/chris1610/pbpython/blob/master/data/salesfunnel.xlsx?raw=True\")\n", "pv = pd.pivot_table(df, index=['Name'], columns=[\"Status\"], values=['Quantity'], aggfunc=sum, fill_value=0)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "trace1 = go.Bar(x=pv.index, y=pv[('Quantity', 'declined')], name='Declined')\n", "trace2 = go.Bar(x=pv.index, y=pv[('Quantity', 'pending')], name='Pending')\n", "trace3 = go.Bar(x=pv.index, y=pv[('Quantity', 'presented')], name='Presented')\n", "trace4 = go.Bar(x=pv.index, y=pv[('Quantity', 'won')], name='Won')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Primeiro vamos ao layout\n", "### Para fazer isso utilizaremos componentes HTML que já conhecemos, como H1, Divs, Tabs, " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "app1 = dash.Dash()\n", "\n", "app1.layout = html.Div([\n", " html.H1('Sales Funnel Report'),\n", " html.Div('National Sales Funnel Report.'),\n", " dcc.Graph(\n", " id='example-graph',\n", " figure={\n", " 'data': [trace1, trace2, trace3, trace4],\n", " 'layout':\n", " go.Layout(title='Order Status by Customer', barmode='stack')\n", " })\n", "])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "app1.run_server(debug=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vamos agora criar uma interação, colocando a opção para o usuário inserir o 'Manager' que ele quer visualizar.\n", "## Faremos isso com um dropdown\n", "## Nele, colocaremos as opções de 'managers' que o usuário poderá selecionar" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import dash\n", "import dash_core_components as dcc\n", "import dash_html_components as html\n", "import plotly.graph_objs as go\n", "import pandas as pd\n", "\n", "df = pd.read_excel(\n", " \"https://github.com/chris1610/pbpython/blob/master/data/salesfunnel.xlsx?raw=True\"\n", ")\n", "mgr_options = list(df[\"Manager\"].unique())\n", "\n", "\n", "\n", "mgr_options.append('All Managers')\n", "\n", "app = dash.Dash()\n", "\n", "app.layout = html.Div([\n", " html.H2(\"Sales Funnel Report\"),\n", " html.Div( # Criaremos outra div\n", " [ \n", " dcc.Dropdown( # E dentro dela um dropdown\n", " id=\"Manager\",\n", " options=[{\n", " 'label': i,\n", " 'value': i\n", " } for i in mgr_options],\n", " value='All Managers'),\n", " ],\n", " style={'width': '25%', # podemos adicionar CSS desta forma\n", " 'display': 'inline-block'}),\n", " dcc.Graph(id='funnel-graph'),\n", "])\n", "\n", "\n", "@app.callback(\n", " dash.dependencies.Output('funnel-graph', 'figure'),\n", " [dash.dependencies.Input('Manager', 'value')])\n", "def update_graph(Manager):\n", " if Manager == \"All Managers\":\n", " df_plot = df.copy()\n", " else:\n", " df_plot = df[df['Manager'] == Manager]\n", "\n", " pv = pd.pivot_table(\n", " df_plot,\n", " index=['Name'],\n", " columns=[\"Status\"],\n", " values=['Quantity'],\n", " aggfunc=sum,\n", " fill_value=0)\n", "\n", " trace1 = go.Bar(x=pv.index, y=pv[('Quantity', 'declined')], name='Declined')\n", " trace2 = go.Bar(x=pv.index, y=pv[('Quantity', 'pending')], name='Pending')\n", " trace3 = go.Bar(x=pv.index, y=pv[('Quantity', 'presented')], name='Presented')\n", " trace4 = go.Bar(x=pv.index, y=pv[('Quantity', 'won')], name='Won')\n", "\n", " return {\n", " 'data': [trace1, trace2, trace3, trace4],\n", " 'layout':\n", " go.Layout(\n", " title='Customer Order Status for {}'.format(Manager),\n", " barmode='stack')\n", " }\n", "\n", "\n", "if __name__ == '__main__':\n", " app.run_server(debug=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Muito interessante as possibilidades correto? Vamos entender um pouco do funcionamento básico dessa biblioteca" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A primeira parte é sobre o layout e depois falaremos sobre as callbacks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Temos abaixo um código simples de um dataset sobre expectativa de vida no mundo." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Run this app with `python app.py` and\n", "# visit http://127.0.0.1:8050/ in your web browser.\n", "\n", "\n", "from dash import Dash, dcc, html\n", "import plotly.express as px\n", "import pandas as pd\n", "\n", "\n", "app = Dash(__name__)\n", "\n", "df = pd.read_csv('https://gist.githubusercontent.com/chriddyp/5d1ea79569ed194d432e56108a04d188/raw/a9f9e8076b837d541398e999dcbac2b2826a81f8/gdp-life-exp-2007.csv')\n", "\n", "fig = px.scatter(df, x=\"gdp per capita\", y=\"life expectancy\",\n", " size=\"population\", color=\"continent\", hover_name=\"country\",\n", " log_x=True, size_max=60)\n", "\n", "app.layout = html.Div([\n", " dcc.Graph(\n", " id='life-exp-vs-gdp',\n", " figure=fig\n", " )\n", "])\n", "\n", "if __name__ == '__main__':\n", " app.run(debug=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Porém ele está muito simples, vamos colocar mais plots nele.." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from dash import Dash, dcc, html\n", "import plotly.express as px\n", "import pandas as pd\n", "\n", "app = Dash(__name__)\n", "\n", "# Carregue os dados do DataFrame\n", "df = pd.read_csv('https://gist.githubusercontent.com/chriddyp/5d1ea79569ed194d432e56108a04d188/raw/a9f9e8076b837d541398e999dcbac2b2826a81f8/gdp-life-exp-2007.csv')\n", "\n", "# Crie a primeira visualização de gráfico (gráfico de dispersão)\n", "fig = px.scatter(df, x=\"gdp per capita\", y=\"life expectancy\",\n", " size=\"population\", color=\"continent\", hover_name=\"country\",\n", " log_x=True, size_max=60)\n", "\n", "# Crie uma segunda visualização de gráfico (por exemplo, um gráfico de barras)\n", "# Substitua os dados e a configuração de gráfico apropriados para a segunda visualização\n", "fig2 = px.bar(df, x=\"country\", y=\"gdp per capita\")\n", "\n", "app.layout = html.Div([\n", " dcc.Graph(\n", " id='life-exp-vs-gdp',\n", " figure=fig\n", " ),\n", " dcc.Graph(\n", " id='gdp-per-capita-bar',\n", " figure=fig2 # Use a segunda visualização de gráfico aqui\n", " )\n", "])\n", "\n", "if __name__ == '__main__':\n", " app.run_server(debug=True)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Que tal deixar ele mais bonito e organizado? CSS nele." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from dash import Dash, dcc, html\n", "import plotly.express as px\n", "import pandas as pd\n", "\n", "app = Dash(__name__)\n", "\n", "# Load the data into a DataFrame\n", "df = pd.read_csv('https://gist.githubusercontent.com/chriddyp/5d1ea79569ed194d432e56108a04d188/raw/a9f9e8076b837d541398e999dcbac2b2826a81f8/gdp-life-exp-2007.csv')\n", "\n", "# Create the first visualization (scatter plot)\n", "fig = px.scatter(df, x=\"gdp per capita\", y=\"life expectancy\",\n", " size=\"population\", color=\"continent\", hover_name=\"country\",\n", " log_x=True, size_max=60)\n", "\n", "# Create the second visualization (bar chart)\n", "fig2 = px.bar(df, x=\"country\", y=\"gdp per capita\")\n", "\n", "app.layout = html.Div([\n", " html.Div([\n", " html.H3(\"Scatter Plot: Life Expectancy vs. GDP Per Capita\"),\n", " dcc.Graph(\n", " id='life-exp-vs-gdp',\n", " figure=fig\n", " ),\n", " ], style={'width': '49%', 'display': 'inline-block'}),\n", " \n", " html.Div([\n", " html.H3(\"Bar Chart: GDP Per Capita by Country\"),\n", " dcc.Graph(\n", " id='gdp-per-capita-bar',\n", " figure=fig2\n", " ),\n", " ], style={'width': '49%', 'display': 'inline-block'})\n", "])\n", "\n", "if __name__ == '__main__':\n", " app.run_server(debug=True)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## E agora funções de interação de dados." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "ename": "", "evalue": "", "output_type": "error", "traceback": [ "\u001b[1;31mO Kernel falhou ao executar o código na célula atual ou em uma célula anterior. Examine o código nas células para identificar uma possível causa da falha. Clique aqui para obter mais informações. Consulte o log do Jupyter para obter mais detalhes." ] } ], "source": [ "from dash import Dash, dcc, html, Input, Output\n", "import plotly.express as px\n", "import pandas as pd\n", "\n", "app = Dash(__name__)\n", "\n", "# Load the data into a DataFrame\n", "df = pd.read_csv('https://gist.githubusercontent.com/chriddyp/5d1ea79569ed194d432e56108a04d188/raw/a9f9e8076b837d541398e999dcbac2b2826a81f8/gdp-life-exp-2007.csv')\n", "\n", "# Create the first visualization (scatter plot)\n", "fig = px.scatter(df, x=\"gdp per capita\", y=\"life expectancy\",\n", " size=\"population\", color=\"continent\", hover_name=\"country\",\n", " size_max=60)\n", "\n", "# Create the second visualization (bar chart)\n", "fig2 = px.bar(df, x=\"country\", y=\"gdp per capita\")\n", "\n", "app.layout = html.Div([\n", " html.Div([\n", " html.H3(\"Scatter Plot: Life Expectancy vs. GDP Per Capita\"),\n", " dcc.RadioItems(\n", " id='log-scale',\n", " options=[\n", " {'label': 'Log Scale', 'value': 'log'},\n", " {'label': 'Linear Scale', 'value': 'linear'}\n", " ],\n", " value='log',\n", " labelStyle={'display': 'block'}\n", " ),\n", " dcc.Graph(\n", " id='life-exp-vs-gdp',\n", " figure=fig\n", " )\n", " ], style={'width': '49%', 'display': 'inline-block'}),\n", " \n", " html.Div([\n", " html.H3(\"Bar Chart: GDP Per Capita by Country\"),\n", " dcc.Graph(\n", " id='gdp-per-capita-bar',\n", " figure=fig2\n", " ),\n", " dcc.Slider(\n", " id='country-count-slider',\n", " min=10,\n", " max=len(df),\n", " step=10,\n", " value=len(df),\n", " marks={i: {'label': str(i), 'style': {'transform': 'rotate(-45deg)'}} for i in range(10, len(df) + 1, 10)},\n", " ),\n", " dcc.Dropdown(\n", " id='sorting-dropdown',\n", " options=[\n", " {'label': 'Sort by Alphabetical Order', 'value': 'alphabetical'},\n", " {'label': 'Sort by GDP per Capita', 'value': 'gdp'},\n", " ],\n", " value='alphabetical',\n", " style={'width': '50%'}\n", " )\n", " ], style={'width': '49%', 'display': 'inline-block'})\n", "])\n", "\n", "@app.callback(\n", " Output('gdp-per-capita-bar', 'figure'),\n", " Input('country-count-slider', 'value'),\n", " Input('sorting-dropdown', 'value')\n", ")\n", "def update_country_count(selected_count, sorting_option):\n", " if sorting_option == 'alphabetical':\n", " sorted_df = df.sort_values(by='country').head(selected_count)\n", " else:\n", " sorted_df = df.sort_values(by='gdp per capita', ascending=False).head(selected_count)\n", " \n", " updated_fig = px.bar(sorted_df, x=\"country\", y=\"gdp per capita\")\n", " return updated_fig\n", "\n", "@app.callback(\n", " Output('life-exp-vs-gdp', 'figure'),\n", " Input('log-scale', 'value')\n", ")\n", "def update_scale(selected_scale):\n", " updated_fig = px.scatter(df, x=\"gdp per capita\", y=\"life expectancy\",\n", " size=\"population\", color=\"continent\", hover_name=\"country\",\n", " size_max=60, log_x=(selected_scale == 'log'))\n", " return updated_fig\n", "\n", "if __name__ == '__main__':\n", " app.run_server(debug=True)\n" ] } ], "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.10.12" } }, "nbformat": 4, "nbformat_minor": 2 }