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)
Related
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')
]
)
])
])
I'm new to Dash and I'm trying to figure out how to set Callback inputs.
My Dash app has graphs that I want to dynamically update with new data on every page load (or refresh.)
I don't want to do it through user interaction such as dropdown, radio button...
To do so I have created hidden divs as callback inputs, but I'm not sure this is the proper way.
Is there any other approach that would be more suitable (or elegant) in this situation?
Please let me know if there’s something else in my code that needs to be changed.
This is my code:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
import json
import plotly.express as px
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions'] = True
data = [['Blue', 30], ['Red ', 20], ['Green', 60]]
df = pd.DataFrame(data, columns=['Color', 'Number'])
data1 = [['A', 10, 88], ['B ', 50, 45], ['C', 25, 120]]
df1 = pd.DataFrame(data1, columns=['Letter', 'Column1', 'Column2'])
def serve_layout():
slayout = html.Div(children=[
html.H1(children='Colors and Letters', style={'text-align': 'center'}),
html.Div([
html.Div(id='input-value', style={'display': 'none'}),
html.Div(id='intermediate-value', style={'display': 'none'}),
]),
html.Div([dcc.Graph(id='graph', style={'width': 1200,
"margin-left": "auto",
"margin-right": "auto",
}),
dcc.Graph(id='graph1', style={'width': 1200,
"margin-left": "auto",
"margin-right": "auto",
})]),
])
return slayout
#app.callback(Output('intermediate-value', 'children'),
[Input('input-value', 'value')])
def clean_data(value):
df_1 = df
df_2 = df1
datasets = {
'df_1': df_1.to_json(orient='split', date_format='iso'),
'df_2': df_2.to_json(orient='split', date_format='iso')
}
return json.dumps(datasets)
#app.callback(
Output('graph', 'figure'),
[Input('intermediate-value', 'children')])
def update_graph(cleaned_data):
datasets = json.loads(cleaned_data)
dff = pd.read_json(datasets['df_1'], orient='split')
fig = go.Figure(data=[go.Bar(x=dff['Color'], y=dff['Number'], text=dff['Number'], textposition='auto')],
layout=go.Layout())
return fig
#app.callback(
Output('graph1', 'figure'),
[Input('intermediate-value', 'children')])
def update_graph(cleaned_data):
datasets = json.loads(cleaned_data)
dff1 = pd.read_json(datasets['df_2'], orient='split')
fig1 = px.line(x=dff1['Letter'], y=dff1['Column1'], color=px.Constant('Column1'),
labels=dict(x='Letter', y='Column1', color='Letter'))
fig1.add_bar(x=dff1['Letter'], y=dff1['Column2'], name='Column2')
return fig1
app.layout = serve_layout
if __name__ == '__main__':
app.run_server(debug=True)
Thanks for any help on this matter.
If you only want to update the plots on page load / refresh, I would advise against any callbacks and instead directly load the figures.
This way, you can leave out all the hidden and intermediate values.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
import json
import plotly.express as px
import numpy as np
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions'] = True
def refresh_data():
data = [['Blue', 30], ['Red ', np.random.random(1)[0] * 10], ['Green', 60]]
df = pd.DataFrame(data, columns=['Color', 'Number'])
data1 = [['A', 10, 88], ['B ', 50, 45], ['C', 25, 120]]
df1 = pd.DataFrame(data1, columns=['Letter', 'Column1', 'Column2'])
return df, df1
def serve_layout():
plot_style = {'width': 1200,
"margin-left": "auto",
"margin-right": "auto",
}
slayout = html.Div(children=[
html.H1(children='Colors and Letters', style={'text-align': 'center'}),
html.Div(
[dcc.Graph(figure=get_graph(), id='graph', style=plot_style),
dcc.Graph(figure=get_graph1(), id='graph1', style=plot_style)]),
])
return slayout
def get_clean_data():
df_1, df_2 = refresh_data()
datasets = {
'df_1': df_1.to_json(orient='split', date_format='iso'),
'df_2': df_2.to_json(orient='split', date_format='iso')
}
return json.dumps(datasets)
def get_graph():
datasets = json.loads(get_clean_data())
dff = pd.read_json(datasets['df_1'], orient='split')
fig = go.Figure(data=[
go.Bar(x=dff['Color'], y=dff['Number'], text=dff['Number'],
textposition='auto')],
layout=go.Layout())
return fig
def get_graph1():
datasets = json.loads(get_clean_data())
dff1 = pd.read_json(datasets['df_2'], orient='split')
fig1 = px.line(x=dff1['Letter'], y=dff1['Column1'],
color=px.Constant('Column1'),
labels=dict(x='Letter', y='Column1', color='Letter'))
fig1.add_bar(x=dff1['Letter'], y=dff1['Column2'], name='Column2')
return fig1
app.layout = serve_layout
if __name__ == '__main__':
app.run_server(debug=True)
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.
I'm new to dash and I'm having problems finding examples on using data frames within a callback. I created a weekly radio button and a monthly radio button.
When the monthly radio button is selected I would like the graph to pull data from df_monthly where each bar would be a monthly sum of pay. When the weekly radio button is checked I would like to see the graph populate each bar on a weekly basis which would be each row in the data frame since I get paid once a week.
I'm not certain where I'm going wrong but I keep receiving an error stating TypeError: update_fig() takes 0 positional arguments but 1 was given
The graph populates without data like the picture below. Thanks for any help on this matter.
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.plotly as py
import plotly.graph_objs as go
import sqlite3
import pandas as pd
from functools import reduce
import datetime
conn = sqlite3.connect('paychecks.db')
df_ct = pd.read_sql('SELECT * FROM CheckTotal',conn)
df_earn = pd.read_sql('SELECT * FROM Earnings', conn)
df_whold = pd.read_sql('SELECT * FROM Withholdings', conn)
data_frames = [df_ct, df_earn, df_whold]
df_paystub = reduce(lambda left,right: pd.merge(left,right,on=['Date'], how='outer'), data_frames)
def date_extraction(df):
df['Date'] = pd.to_datetime(df['Date'])
df['Year'] = df['Date'].dt.strftime('%Y')
df['Month'] = df['Date'].dt.strftime('%B')
df['Day'] = df['Date'].dt.strftime('%d')
return df
date_extraction(df_paystub)
df_monthly = df_paystub.groupby(['Month']).sum()
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'})
app.layout = html.Div(children=[
html.Div([
html.Div([
dcc.RadioItems(
id='data-view',
options=[
{'label': 'Weekly', 'value': 'Weekly'},
{'label': 'Monthly', 'value': 'Monthly'},
],
value='',
labelStyle={'display': 'inline-block'}
),
], className = 'two columns'),
html.Div([
dcc.Dropdown(
id='year-dropdown',
options=[
{'label': i, 'value': i} for i in df_paystub['Year'].unique()
],
placeholder="Select a year",
),
], className='five columns'),
html.Div([
dcc.Dropdown(
id='month-dropdown',
options=[
{'label': i, 'value': i} for i in df_paystub['Month'].unique()
],
placeholder="Select a month(s)",
multi=True,
),
], className='five columns'),
], className = 'row'),
# HTML ROW CREATED IN DASH
html.Div([
# HTML COLUMN CREATED IN DASH
html.Div([
# PLOTLY BAR GRAPH
dcc.Graph(
id='pay',
)
], className = 'six columns'),
# HTML COLUMN CREATED IN DASH
html.Div([
# PLOTLY LINE GRAPH
dcc.Graph(
id='hours',
figure={
'data': [
go.Scatter(
x = df_earn['Date'],
y = df_earn['RegHours'],
mode = 'lines',
name = 'Regular Hours',
),
go.Scatter(
x = df_earn['Date'],
y = df_earn['OtHours'],
mode = 'lines',
name = 'Overtime Hours',
)
]
}
)
], className='six columns')
], className='row')
], className='ten columns offset-by-one')
#app.callback(dash.dependencies.Output('pay', 'figure'),
[dash.dependencies.Input('data-view', 'value')])
def update_fig():
figure={
'data': [
go.Bar(
x = df_monthly['Month'],
y = df_monthly['CheckTotal'],
name = 'Take Home Pay',
),
go.Bar(
x = df_monthly['Month'],
y = df_monthly['EarnTotal'],
name = 'Earnings',
)
],
'layout': go.Layout(
title = 'Take Home Pay vs. Earnings',
barmode = 'group',
yaxis = dict(title = 'Pay (U.S. Dollars)'),
xaxis = dict(title = 'Date Paid')
)
}
return figure
if __name__ == "__main__":
app.run_server(debug=True)
Hi #prime90 and welcome to Dash.
In glancing at your callback signature it looks like the update_fig() function needs to take the Input you've given it (using dash.dependencies.Input).
The callback is sending this Input what changes in your app you've specified. So it's sending along the value of #data-view you've given to your function update_fig(), which doesn't currently accept any variables, causing the error message.
Just update your function signature and add a couple of boolean variables to rid yourself of the error and get the potential functionality:
def update_fig(dataview_value):
# define your weekly OR monthly dataframe
# you'll need to supply df_weekly similarly to df_monthly
# though DO NOT modify these, see note below!
df = df_weekly if dataview == 'weekly' else df_monthly
dfkey = 'Week' if 'week' in df.columns else 'Month' # eh, worth a shot!
figure={
'data': [
go.Bar(
x = df[dfkey],
y = df['CheckTotal'],
name = 'Take Home Pay',
),
go.Bar(
x = df[dfkey],
y = df['EarnTotal'],
name = 'Earnings',
)
],
'layout': go.Layout(
title = 'Take Home Pay vs. Earnings',
barmode = 'group',
yaxis = dict(title = 'Pay (U.S. Dollars)'),
xaxis = dict(title = 'Date Paid')
)
}
return figure
As was written in the comments above, you'll need to do some type of prior manipulation to create a df_weekly, as you have with your current df_monthly.
In addition, the code snippet I wrote assumes the df column is named "Week" and "Month"--obviously update these as is necessary.
Data manipulation in Dash:
Ensure you read the data sharing docs, as they highlight how data should never be modified out of scope.
I hope this helps :-)
I am trying to create some chart using Dash for Python. I have some file with values that I want to read in, save the values in a list and use it to create the graph. My code:
app = dash.Dash()
app.layout = html.Div([
html.H1('Title'),
dcc.Dropdown(
id='my-dropdown',
options=[
{'label': 'Fruit', 'value': 'FRUIT'}
# {'label': 'Tesla', 'value': 'TSLA'},
# {'label': 'Apple', 'value': 'AAPL'}
],
value='TEMPERATUR'
),
dcc.Slider(
min=-5,
max=10,
step=0.5,
value=-3,
),
dcc.Graph(id='my-graph', animate=True),
])
path = "/../example.csv"
with open(path,"r") as file:
reader = csv.reader(file)
dataCopy=[]
for line in file:
dataCopy.append(line)
arrayValues = np.array(dataCopy)
#app.callback(Output('my-graph', 'figure'), [Input('my-dropdown', 'value')])
def update_graph(selected_dropdown_value):
return {
'data': arrayValues }
if __name__ == '__main__':
app.run_server(
)
When I print the arrayValues I get:
['28.687', '29.687', '24.687', '21.687', '25.687', '28.687']
But when I check my graph it has no values shown on it. Do you know what could my mistake be?
UPDATE: I tried with the line
arrayValues = list(map(float, arrayValues))
after getting it as a suggestion in the comments, but still no workable code.
You need to provide some additional information to the Graph data field,
If you want the arrayValues to be plotted in Y axis in a line graph the following code should work.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import plotly.graph_objs as go
#hardcoding arrayValues since csv is not provided
arrayValues = ['28.687', '29.687', '24.687', '21.687', '25.687', '28.687']
app = dash.Dash()
app.layout = html.Div([
html.H1('Title'),
dcc.Dropdown(
id='my-dropdown',
options=[
{'label': 'Fruit', 'value': 'FRUIT'}
# {'label': 'Tesla', 'value': 'TSLA'},
# {'label': 'Apple', 'value': 'AAPL'}
],
value='TEMPERATUR'
),
dcc.Slider(
min=-5,
max=10,
step=0.5,
value=-3,
),
dcc.Graph(id='my-graph', animate=True),
])
#path = "/../example.csv"
#with open(path,"r") as file:
# reader = csv.reader(file)
# dataCopy=[]
# for line in file:
# dataCopy.append(line)
# arrayValues = np.array(dataCopy)
#app.callback(Output('my-graph', 'figure'), [Input('my-dropdown', 'value')])
def update_graph(selected_dropdown_value):
return {
'data': [
{'y': arrayValues}
]
}
if __name__ == '__main__':
app.run_server(
)
As Dash uses plotly graph representation, you can refer to the official plotly docs to a variety of such Graphs.
Here is the documentation,
https://plot.ly/python/basic-charts/