Plotly Callbacks Dynamic Table - python

Hi I'm trying to understand how I can do this using only one data source or data frame in pandas python. (Plotly)
Let's say that I have a dataframe that is compiled of sample sales data:
e.g.
date (month) | client name | sales rep name | total_sales
YYYY-M Jane Doe Adam float
My sample layout has a chained callback that displays and organizes:
Dropdown1: Sales Rep Name
Dropdown2: Client Names (These Clients are unique to the selected Sales Rep Name)
Graph of x= Date, y = Sales ^^^ determined by these selected
I want to make a month over month table or even a visual (line graph) that generates based on the selected at the top but how would I go about it?
Is there a built in function for Month Over Month growth?
Please help in steps this is greatly appreciated.
import dash
from dash import dcc as dcc
from dash import html as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv(r"C:\Users\rbricker\Desktop\sales.csv")
app.layout = html.Div([
html.Label("Sales Rep Names:", style={'fontSize': 30, 'textAlign': 'center'}),
dcc.Dropdown(
id='sales-rep',
options=[{'label': s, 'value': s} for s in sorted(df.SalesRepName.unique())],
value='Adam',
clearable=False
),
html.Label("Clients", style={'fontSize': 30, 'textAlign': 'center'}),
dcc.Dropdown(id='client-name', options=[], multi=True),
dcc.Graph(id='display-chart', figure={})
])
#app.callback(
Output('client-name', 'options'),
Input('sales-rep', 'value')
)
def set_client_options(chosen_sales_rep):
dff = df[df.SalesRepName == chosen_sales_rep]
return [{'label': c, 'value': c} for c in sorted(dff.Clients.unique())]
#app.callback(
Output(client-name', 'value'),
Input('client-name', 'options')
)
def set_client_name_value(available_options):
return [x['value'] for x in available_options]
#app.callback(
Output('display-chart', 'figure'),
Input('client-name', 'value'),
Input('sales-rep', 'value')
)
def update_graph(selected_client_name, selected_sales_rep):
if len(selected_client_name) == 0:
return dash.no_update
else:
dff = df[(df.SalesRepName == selected_sales_rep) & (df.Clients.isin(selected_client_name))]
fig = px.line(dff, x='DatePeriod', y='total',
color='Clients',
hover_name='Clients')
return fig
if __name__ == '__main__':
app.run_server(debug=True)

Related

multiple chained callbacks in plotly (date range picker)

I have a dictionary, which contains of 3 dataframes (columns are identical), two dropdowns and one date range picker. First dropdown to choose the dataframe, the second to choose the columns. I have implemented 2 chained callbacks for dropdowns and now I want to create a third chained DatePickerRange which gives the Date through DatePickerRange. So in steps, first we select the dataframe, the filtered list of columns appears for that dataframe and as a next step, I want the DatePickerRange to get updated with the min and max Date values of that dataframes' column (date).
I tried to do something on my own but it doesn't work, my major doubts are I can't find a way to fill in start_date, end_date and I do need a third #app.callback but I don't know how to further do that. Thank you in advance. Here's the code:
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
from dash.dependencies import Input, Output, State
import urllib.request
import dash
import datetime as dt
import pandas as pd
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import plotly
import plotly.express as px
import pandas as pd
import requests
from datetime import datetime
import plotly.graph_objects as go
df1 = {'date': ['2021-07-17 04:00:03', '2021-07-18 06:02:25', '2021-07-18 06:02:25'], 'prices': [31370, 35370, 32370]}
df1 = pd.DataFrame(data=df1)
df2 = {'date': ['2021-07-17 04:10:03', '2021-07-18 06:27:25', '2021-07-18 09:02:25'], 'prices': [1370, 8370, 2370]}
df2 = pd.DataFrame(data=df2)
df3 = {'date': ['2021-07-18 05:10:08', '2021-07-19 06:27:25', '2021-07-19 09:02:25'], 'prices': [24, 58, 123]}
df3 = pd.DataFrame(data=df3)
dict_main = {'df1': df1, 'df2': df2, 'df3': df3}
#----------------------------------------------------------------------
app = dash.Dash(__name__)
server = app.server
rpm = list(dict_main.keys())
channels = dict_main[rpm[0]]
for speed in rpm:
start_date = dict_main[speed]['date'][0]
end_date = dict_main[speed]['date'].to_list()[-1]
for speed in rpm:
start_date = dict_main[speed]['date'][0]
end_date = dict_main[speed]['date'].to_list()[-1]
app.layout = html.Div(
[
html.Div([
dcc.Dropdown(
id='rpm-dropdown',
options=[{'label':speed, 'value':speed} for speed in rpm],
value=list(dict_main.keys())[0],
searchable=True
),
],style={'width': '20%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='channel-dropdown',
multi=True,
),
],style={'width': '20%', 'display': 'inline-block'}
),
html.Div([
dcc.DatePickerRange(
id = 'daterange',
start_date = start_date,
end_date = end_date
),
], style={'width': '98%', 'display': 'inline-block'}
),
html.Div([
dcc.Graph(
id='Main-Graph'
),
], style={'width': '98%', 'display': 'inline-block'}
)
]
)
#app.callback(
Output('channel-dropdown', 'options'),
[Input('rpm-dropdown', 'value')])
def update_date_dropdown(speed):
return [{'label': i, 'value': i} for i in dict_main[speed].drop(columns = 'date')]
#app.callback(
Output('Main-Graph', 'figure'),
[Input('channel-dropdown', 'value')],
[State('rpm-dropdown', 'value'),
State('daterange', 'start_date'),
State('daterange', 'end_date')])
def updateGraph(channels, test, start_date, end_date):
for speed in rpm:
dff = dict_main[speed]
dff = dff[(dff['date'] > dict_main[speed]['date'][0]) & (dff['date'] < dict_main[speed]['date'].to_list()[-1])]
if channels:
return go.Figure(data=[go.Scatter(x=dict_main[test]['date'], y=dict_main[test][i], name=i) for i in channels])
else:
return go.Figure(data=[])
if __name__ == '__main__':
app.run_server(port =8050)

Plotly: How to create 'input text' on one page and output (graphs) on second page or tab, by using plotly-dash?

I am creating an app where the first page should take only 'text input' and results(graph) must show on second page or new tab. I do not want text input and charts on the same page. It means, if I write the input as 'USA' in text input bar, the graph of USA should populate on second tab. Following is the working code that I have written so far in dropdown format. In this code, dropdown and graphs are on the same page which I do not want. Please suggest.
import pandas as pd
import plotly.express as px
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Output, Input
import numpy as np
import plotly.io as pio
pio.renderers.default='browser'
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1("Economy Analysis"),
dcc.Dropdown(id='Country_select',
options=[{'label': x, 'value': x}
for x in df.Country.unique()],
value = 'USA'
),
dcc.Graph(id ='my-graph', figure = {})
])
#app.callback(
Output(component_id = 'my-graph', component_property = 'figure'),
Input(component_id = 'Country_select', component_property = 'value'))
def interactive_graphing(value_country):
print(value_country)
s = 100
cat_g = ["developing","develop"]
sample_cat = [cat_g[np.random.randint(0,2)]for i in range(100)]
df = pd.DataFrame({"Country": np.random.choice(["USA", "JPY", "MEX", "IND", "AUS"], s),
"Net": np.random.randint(5, 75, s),
})
df["sample_cat"] = sample_cat
df = df[df.Country==value_country]
df2 = df.pivot_table(index='Country',columns='sample_cat',values='Net',aggfunc='sum')
df2.reset_index(inplace=True)
fig = px.bar(df2, x="Country",
y=['develop','developing'])
return fig
if __name__=='__main__':
app.run_server()
You can use dcc.Tabs and dcc.Tab containers in your layout, and put the input/graph in separate tabs. Dash bootstrap components tabs would also work for this. The ids will still work as inputs/outputs with your callback.
Sample layout:
app.layout = html.Div([
html.H1("Economy Analysis"),
dcc.Tabs([
dcc.Tab(
label='Dropdown',
children=[
dcc.Dropdown(id='Country_select',
options=[{'label': x, 'value': x}
for x in df.Country.unique()],
value = 'USA')
]
),
dcc.Tab(
label='Graph',
children=[
dcc.Graph(id ='my-graph')
]
)
])
])

Dynamically update the title in Dash Plotly

I have created this very simplified example in which I would like to dynamically update the title of a chart as a dropdown label changes.
Here's the code:
data = {'Stock': ['F', 'NFLX', 'AMZN'], 'Number': [10, 15, 7]}
df = pd.DataFrame(data, columns=['Stock', 'Number'])
stock_options = df['Stock']
app = dash.Dash(__name__)
app.layout = html.Div(children=[
html.H1(children='Example Bar Chart'),
html.Div([
dcc.Dropdown(
id='dropdown',
options=[{'label': i, 'value': i} for i in stock_options],
value='F',
),
html.Div(dcc.Graph(id='graph')),
]),
])
#app.callback(
Output(component_id='graph', component_property='figure'),
Input(component_id='dropdown', component_property='value')
)
def update_graph(stock):
msk = df.Stock.isin([stock])
figure = px.bar(df[msk], x='Stock', y='Number', title=f"{stock} open price")
return figure
if __name__ == '__main__':
app.run_server(debug=True)
So, while keeping the same label in dropdown instead of 'F open price' in the title I would like to get 'Facebook open price'... and so on.
I've tried to solve this with map but I couldn't get it working. Can someone point me in the direction on how to resolve this?
Thanks in advance.
As I wrote in my comment, not sure how you want to store the mapping between symbol name and the displayed title in the graph. Here is one solution that works using a dictionary stock_name_mapping that contains the symbols als keys and the displayed names as values:
import pandas as pd
import dash
from dash.dependencies import Input, Output
import dash_html_components as html
import dash_core_components as dcc
import plotly.express as px
data = {'Stock': ['F', 'NFLX', 'AMZN'], 'Number': [10, 15, 7]}
df = pd.DataFrame(data, columns=['Stock', 'Number'])
stock_options = df['Stock']
stock_name_mapping = {'F': 'Facebook',
'NFLX': 'Netflix',
'AMZN': 'Amazon'}
app = dash.Dash(__name__)
app.layout = html.Div(children=[
html.H1(children='Example Bar Chart'),
html.Div([
dcc.Dropdown(
id='dropdown',
options=[{'label': i, 'value': i} for i in stock_options],
value='F',
),
html.Div(dcc.Graph(id='graph')),
]),
])
#app.callback(
Output(component_id='graph', component_property='figure'),
Input(component_id='dropdown', component_property='value')
)
def update_graph(stock):
msk = df.Stock.isin([stock])
stock_name = stock_name_mapping[stock]
figure = px.bar(df[msk], x='Stock', y='Number', title=f"{stock_name} open price")
return figure
if __name__ == '__main__':
app.run_server(debug=True)

Graph_Update with two dropdown with multiple selection using excel data and dash python

I am trying to update a graph in dash using an excel with data. I have 2 drop down and an excel document with different sheets for each drop down. I couldn't manage yet to select a value from drop down and to charge that data into the table (I have also a table before the graph) and plot values into the graph.
import dash
import dash_auth
import dash_core_components as dcc
import dash_html_components as html
import plotly
import dash_daq as daq
import os
import random
import pandas as pd
import plotly.graph_objs as go
from collections import deque
import psycopg2
from dash.dependencies import Output, Input
DB_NAME = "LicentaTest"
DB_USER = "postgres"
DB_PASS = "admin"
DB_HOST = "localhost"
DB_PORT = "5433"
VALID_USERNAME_PASSWORD_PAIRS = [
['admin1', 'admin']
]
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(_name_, external_stylesheets=external_stylesheets)
auth = dash_auth.BasicAuth(
app,
VALID_USERNAME_PASSWORD_PAIRS
)
df = pd.read_excel('UploadData.xlsx', sheet_name='Total')
def generate_table(dataframe, max_rows=13):
return html.Table(
# Header
[html.Tr([html.Th(col) for col in dataframe.columns])] +
# Body
[html.Tr([
html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
]) for i in range(min(len(dataframe), max_rows))]
)
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(_name_, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.H1('Electrica SDEE Transilvania SUD SA'),
html.H4('Select the branch:'),
dcc.Dropdown(
id='dropdown',
options=[{'label': i, 'value': i} for i in ['ALBA', 'BRASOV',
'COVASNA', 'HARGHITA', 'MURES', 'SIBIU', 'TOTAL']],
value='',
placeholder = 'Select branch'
#multi = True
),
html.H4('Select the year:'),
dcc.Dropdown(
id='dropdown1',
options=[{'label': i, 'value': i} for i in ['2012', '2013',
'2014', '2015', '2016', '2017', '2018', 'ALL']],
value='',
placeholder = 'Select year'
),
html.Br(),
html.Button('OK', id='submit-form'),
html.Br(),
html.Div(children=[
html.H4(children='Own Technological Consumption'),
generate_table(df),
]),
html.Br(),
html.Br(),
html.Br(),
dcc.Graph(id='graph')],
className='container')
#app.callback(
dash.dependencies.Output('graph', 'figure'),
[dash.dependencies.Input('dropdown', 'value')])
def update_graph1(dropdown_value):
df = pd.read_excel('UploadData.xlsx', sheet_name='Total')
X1 = df.Date.values
Y1 = df.CPT.values
data = plotly.graph_objs.Scatter(
x=X1,
y=Y1,
name='Graph',
mode='lines+markers'
)
return {
'data': [data], 'layout' : go.Layout(xaxis=dict(range[min(X1),max(X1)]),
yaxis=dict(range=[min(Y1),max(Y1)]),
)
}
if _name_ == '_main_':
app.run_server(debug=True)
I expect, when select the value Alba from drop down and year 2015 to show me on table all the values related to this and to plot the CPT function of data.

A single datepicker for multiple dash tables

I would like to select dates in several tables, using dash_table . This works when using a different date picker for each table, but not when using a single date picker for all separate tables.
A simple reproducible example shows a single table, and data can be selected and displayed for different dates (here 1st, 2nd, or 3rd January).
My question: how to make three tables, – one for each country -, using a single date picker (not three). Thank you very much in advance for any suggestions!
Modules
import pandas as pd
import plotly.graph_objs as go
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, Event
import datetime
from datetime import datetime as dt
Fictive DataFrame
df = pd.DataFrame({'dd':['2019-01-01', '2019-01-01', '2019-01-01', '2019-01-02', '2019-01-02', '2019-01-02', '2019-01-03', '2019-01-03'], 'country':['Belgium', 'Belgium','France', 'France', 'Belgium', 'France', 'Belgium', 'Germany'], 'value':[10,20,30,10,15,25,5,70]})
Script
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions']=True
currentday = 1
currentmonth = 1
currentyear = 2019
app.layout = html.Div(
[
html.H4('All countries'),
dcc.DatePickerSingle(
id='my-date-picker-single1',
min_date_allowed=dt(2012, 1, 1),
max_date_allowed=dt(2019, 2, 25),
initial_visible_month=dt(currentyear, currentmonth, currentday),
date=dt(currentyear, currentmonth, currentday),
disabled=False
),
dcc.Store(id="selected-rows1", storage_type="memory"),
html.Div(id="tables-container1"),
dash_table.DataTable(
id="table1",
columns=[{"name": i, "id": i} for i in ['dd', 'country', 'value'] ],
style_cell_conditional=[
{
'if':{'filter':'Country eq "France"'},
'backgroundColor':'rgb(150, 150, 150)'
}
] + [
{'if': {'column_id': c},
'textAlign': 'left'
} for c in ['dd', 'country']
],
sorting=True,
sorting_type='multi',
sorting_settings=[],
)
]
)
#app.callback(
Output("selected-rows1", "data"),
[Input("my-date-picker-single1", "date")],
[State("selected-rows1", "data")],
)
def display_output(value, storage):
if value is not None:
return {"selected_rows1": df[df["dd"].str.contains(value)].to_json()}
#app.callback(
Output("table1", "data"),
[Input("table1", "sorting_settings"), Input("selected-rows1", "data")],
)
def update_graph(sorting_settings, rows):
_df = pd.read_json(rows["selected_rows1"])
if sorting_settings is not None and len(sorting_settings):
for setting in sorting_settings:
_df.sort_values(
by=setting["column_id"],
ascending=(setting["direction"] == "asc"),
inplace=True,
)
return _df.to_dict("rows")
else:
return _df.to_dict("rows")
if __name__ == "__main__":
app.run_server(debug=True)
Your advice is highly appreciated!
You should use multiple callbacks. Check section on "Multiple Outputs". Example:
#app.callback(
Output("selected-rows1", "data"),
[Input("my-date-picker-single1", "date")],
[State("selected-rows1", "data")])
def display_output_1(value, storage):
if value is not None:
return {"selected_rows1": df[df["dd"].str.contains(value)].to_json()}
#app.callback(
Output("selected-rows2", "data"),
[Input("my-date-picker-single1", "date")],
[State("selected-rows2", "data")])
def display_output_2(value, storage):
if value is not None:
return {"selected_rows2": df[df["dd"].str.contains(value)].to_json()}

Categories

Resources