Plotly Dash: Dropdown component callback visibility bug - python

I've been working on an app recently using Dash. The app uses a number of controls, for example Input and Dropdown from the core components. One feature I wanted to include was that only one of the Input or Dropdown is visible at a time, and which one is visible is conditional on what the user chooses (i.e., we use a callback). Here's a minimal example:
import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
controls = dbc.Card(
[
dbc.FormGroup(
[
dbc.Label("Choose input or dropdown"),
dbc.RadioItems(
id='radio',
options=[
{'label': 'input', 'value': 'input'},
{'label': 'dropdown', 'value': 'dropdown'},
],
value='input',
),
]
),
dbc.FormGroup(
[
dbc.Label("Input", id='input-label'),
dbc.Input(
id='input',
type='number',
min=1, max=100, step=1, value=5
),
]
),
dbc.FormGroup(
[
dbc.Label("Dropdown", id='dropdown-label'),
dcc.Dropdown(
id='dropdown',
options=[
{'label': 'Hello'+str(i), 'value': 'Hello'+str(i)} for i in range(100)
],
multi=True,
placeholder='Say Hello',
),
]
),
],
body=True,
color='light',
)
app.layout = dbc.Container(
[
dbc.Row(
[
dbc.Col(controls, md=4)
],
align='center',
),
],
fluid=True,
)
#app.callback(
[Output('input', 'style'),
Output('input-label', 'style'),
Output('dropdown', 'style'),
Output('dropdown-label', 'style')],
[Input('radio', 'value')])
def visibility(selected_type):
if selected_type == 'input':
return {'display': 'block'}, {'display': 'block'}, {'display': 'none'}, {'display': 'none'}
else:
return {'display': 'none'}, {'display': 'none'}, {'display': 'block'}, {'display': 'block'}
if __name__ == "__main__":
app.run_server(debug=True)
However, using the callback ruins the functionality of the Dropdown. For example, try including 10 or so "Hello's" in the Dropdown. Now, if you comment out the callback in the code, the functionality is restored: adding many "Hello's" causes the Dropdown box to expand to store them, as intended.
Could someone explain why my callback is causing this behaviour?

The issue is that you are directly overwriting the styles of the input component and of the dropdown component in the callback. In order to prevent this issue you can assign an id to their containers, and then change the styles of the containers in the callback. With this approach both the input component and the dropdown component will retain their default behaviour.
import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
controls = dbc.Card(
[
dbc.FormGroup(
[
dbc.Label('Choose input or dropdown'),
dbc.RadioItems(
id='radio',
options=[
{'label': 'input', 'value': 'input'},
{'label': 'dropdown', 'value': 'dropdown'},
],
value='input',
),
]
),
dbc.FormGroup(id='input-form', children=
[
dbc.Label('Input', id='input-label'),
dbc.Input(
id='input',
type='number',
min=1, max=100, step=1, value=5
),
]
),
dbc.FormGroup(id='dropdown-form', children=
[
dbc.Label('Dropdown', id='dropdown-label'),
dcc.Dropdown(
id='dropdown',
options=[
{'label': 'Hello'+str(i), 'value': 'Hello'+str(i)} for i in range(100)
],
multi=True,
placeholder='Say Hello',
),
]
),
],
body=True,
color='light',
)
app.layout = dbc.Container(
[
dbc.Row(
[
dbc.Col(controls, md=4)
],
align='center',
),
],
fluid=True,
)
#app.callback([Output('input-form', 'style'), Output('dropdown-form', 'style')],
[Input('radio', 'value')])
def visibility(selected_type):
if selected_type == 'input':
return {'display': 'block'}, {'display': 'none'}
else:
return {'display': 'none'}, {'display': 'block'}
if __name__ == '__main__':
app.run_server(debug=True)

Related

How to set a Radio Button Group's width to fill the width of the parent container in Bootstrap?

Is there a way to set Radio Button Groups that span the width of the parent container / dbc.column? I am currently using Dash Plotly and Python to create a web app and the Radio Button Groups I've created in a column of width 2 do not span the width of the column despite numerous attempts. Here's how I am defining the Radio Button Group using the tutorial found at the bottom of the page here.
html.Div([
dbc.RadioItems(
id="pr-select",
className="btn-group d-flex",
labelClassName="btn btn-info",
labelCheckedClassName="active",
style={'width': '100%'},
options=[{'label': 'Opt1', 'value': 'True', 'disabled': 'True'},
{'label': 'Opt2', 'value': 'False', 'disabled': 'True'},
],
),
],
className='radio-group mb-2',
style={'width': '100%'}
),
As you can see, I've already tried setting the width to 100% in the style, however that has had no effect to the width at all. For reference, this is what it outputs on the app. As you can see, all the radio groups span different widths relative to the column they are in. Any help would be greatly appreciated!
EDIT:
I've included sample code below if you would like to reproduce this and play with the CSS. Please also note that the file must be called app.py and must live in a directory with a folder called assets with a mystyle.css file using the custom css listed at the bottom of the page here:
import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_html_components as html
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
server = Flask(__name__)
app = dash.Dash(__name__, server=server,
external_stylesheets=[dbc.themes.FLATLY],
suppress_callback_exceptions=True,
meta_tags=[{'name': 'viewport',
'content': 'width=device-width, initial-scale=1.0'}],
)
app.layout = dbc.Container([
dbc.Row([
dbc.Col([
html.Div([
dbc.RadioItems(
id="hand-select",
className="btn-group",
labelClassName="btn btn-info",
labelCheckedClassName="active",
options=[
{'label': 'Opt1', 'value': 'Left', 'disabled': 'True'},
{'label': 'Opt2', 'value': 'Both', 'disabled': 'True'},
{'label': 'Opt3', 'value': 'Right', 'disabled': 'True'},
],
style={"margin-top": "auto",
}
),
],
className='radio-group mb-2',
style={'width': '100%'}
#style={'max-width': 'fit-content'}
),
html.Div([
dbc.RadioItems(
id="pr-select",
className="btn-group d-flex",
labelClassName="btn btn-info",
labelCheckedClassName="active",
#inputClassName='mw-100',
style={'width': '100%'},
options=[
{'label': 'Opt1', 'value': 'True', 'disabled': 'True'},
{'label': 'Opt2', 'value': 'False', 'disabled': 'True'},
],
),
],
className='radio-group mb-2',
style={'width': '100%'}
),
html.Div([
dbc.RadioItems(
id="cs-select",
className="btn-group",
labelClassName="btn btn-info",
labelCheckedClassName="active",
options=[
{'label': 'Option One.........', 'value': 'True', 'disabled': 'True'},
{'label': 'Option Two.........', 'value': 'False', 'disabled': 'True'},
],
),
],
className='radio-group mb-2'
),
], width=3, style={'margin-right': '0px',
'margin-left': '0px',
'backgroundColor': 'black'},),
dbc.Col([
], width=3),
dbc.Col([
], width=6)
])
]
)
if __name__ == '__main__':
app.run_server(debug=True)
RadioItems generates HTML like this
<div id="pr-select">
<div class="form-check">
<input type="radio" ...>
<label ... >Opt1</label>
</div>
<div class="form-check">
<input type="radio" ...>
<label ... >Opt2</label>
</div>
</div>
And it needs 'width':'100%' in three places:
in external <div id="pr-select"> and this can be added using style={'width':'100%'}
in <label ... > and this can be added using styleLabel={'width':'100%'}
in <div class="form-check"> and this has no method in code.
The only solution which I found is to create file assets/style.css which dash will load automatically
(documentation: Adding CSS & JS and Overriding the Page-Load Template)
.form-check {
width: 100%;
}
assets/style.css
.form-check {
width: 100%;
}
main.py
import dash
from dash import dcc, html
import dash_bootstrap_components as dbc
from flask import Flask
server = Flask(__name__)
app = dash.Dash(__name__, server=server,
external_stylesheets=[dbc.themes.FLATLY],
suppress_callback_exceptions=True,
meta_tags=[{'name': 'viewport',
'content': 'width=device-width, initial-scale=1.0'}],
)
app.layout = dbc.Container([
dbc.Row([
dbc.Col([
html.Div([
dbc.RadioItems(
id="hand-select",
className="btn-group",
labelClassName="btn btn-info",
labelCheckedClassName="active",
inputClassName="btn-check",
options=[
{'label': 'Opt1', 'value': 'Left', 'disabled': 'True'},
{'label': 'Opt2', 'value': 'Both', 'disabled': 'True'},
{'label': 'Opt3', 'value': 'Right', 'disabled': 'True'},
],
style={'width': '100%'}, # <--- for external <div>
labelStyle={'width': '100%'}, # <--- for <input>
)
],
className="radio-group",
style={"margin-top": "5px", "margin-bottom": "5px"}
),
html.Div([
dbc.RadioItems(
id="pr-select",
className="btn-group",
labelClassName="btn btn-info",
labelCheckedClassName="active",
inputClassName="btn-check",
options=[
{'label': 'Opt1', 'value': 'True', 'disabled': 'True'},
{'label': 'Opt2', 'value': 'False', 'disabled': 'True'},
],
style={'width': '100%'}, # <--- for external <div>
labelStyle={'width':'100%'}, # <--- for <input>
)
],
className="radio-group",
style={"margin-top": "5px", "margin-bottom": "5px"}
),
html.Div([
dbc.RadioItems(
id="cs-select",
className="btn-group",
labelClassName="btn btn-info",
labelCheckedClassName="active",
inputClassName="btn-check",
options=[
{'label': 'Option One.........', 'value': 'True', 'disabled': 'True'},
{'label': 'Option Two.........', 'value': 'False', 'disabled': 'True'},
],
style={'width':'100%'}, # <--- for external <div>
labelStyle={'width':'100%'}, # <--- for <input>
)
],
className="radio-group",
style={"margin-top": "5px", "margin-bottom": "5px"}
),
],
width=3, style={'margin-right': '0px',
'margin-left': '0px',
'backgroundColor': 'black'},
),
])
])
if __name__ == '__main__':
#app.debug=True
app.run_server()

Python Dash Dropdown

There are six questions to be asked to the user. If the user answers these questions, I am trying to make an application that will determine the result of which research design to use on the right. I am doing this application with python dash. My Python code is as follows. How do I write a python code that can bring the result of the research design according to the answers given after the user answers the questions? How should I write the callback code in the dash program for this? Thank you so much in advance.
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from sympy import *
az = ""
bz = ""
app = dash.Dash(external_stylesheets=[dbc.themes.FLATLY])
app.config.suppress_callback_exceptions = True
logo = "analiz.png"
title = dcc.Link(id='ustbaslik',
href="/",
className="navbar-brand",
style={"margin-top": "12px"})
acıklama = [
dbc.CardHeader(id='acik'),
dbc.CardBody([
html.H5(id='ortabaslik', className="card-title"),
html.P(id='ortamesaj', className="card-text text-justify",),
]),
]
sonuc = [
dbc.CardHeader(id='sonuc'),
dbc.CardBody([
html.P(id='mesaj', className="card-text text-justify",),
]),
]
app.layout = html.Div([
html.Nav([
dbc.Container([
dbc.Row([
dbc.Col(title, align="left",width="auto"),
dbc.Col("", align="left",width="%100"),
],
justify="between",
align="center",
),
dbc.Row([
dbc.Col(
html.Div([
html.Button('Türkçe', id='btn-nclicks-1'),
html.Button('İngilizce', id='btn-nclicks-2'),
])
),
],
justify="between",
align="center",
)
])
],
className="navbar navbar-dark bg-dark navbar-expand-md bg-light sticky-top",
),
dbc.Container(
dbc.Row([
dbc.Col(dbc.Card(acıklama, color="primary", inverse=True)),
dbc.Col(
html.Div(children=[
html.Label('Araştırmadaki Değişken Türünü Giriniz:'),
dcc.Dropdown(
options=[
{'label': 'Nitel', 'value': 'nitel'},
{'label': 'Nicel', 'value': 'nicel'}
],
value='tur'
),
html.Hr(),
html.Label('Girişim var mı'),
dcc.Dropdown(
options=[
{'label': 'Evet', 'value': 'evet'},
{'label': 'Hayır', 'value': 'hayır'}
],
value='gir'
),
html.Hr(),
html.Label('Hipotez var mı:'),
dcc.Dropdown(
options=[
{'label': 'Evet', 'value': 'evet'},
{'label': 'Hayır', 'value': 'hayır'}
],
value='hip'
),
html.Hr(),
html.Label('Hasta sayısı:'),
dcc.Dropdown(
options=[
{'label': 'Bir hasta', 'value': 'bir'},
{'label': 'Birden fazla hasta', 'value': 'birden'},
{'label': 'Bir grup hasta', 'value': 'grup'}
],
value='has'
),
html.Hr(),
html.Label('Araştırma sorusunun yönü:'),
dcc.Dropdown(
options=[
{'label': 'Yok', 'value': 'yok'},
{'label': 'Geriye', 'value': 'geri'},
{'label': 'İleriye', 'value': 'ileri'}
],
value='yon'
),
html.Hr(),
html.Label('Araştırmadan elde edilen ölçüt:'),
dcc.Dropdown(
options=[
{'label': 'Prevelans Hızı', 'value': 'pre'},
{'label': 'Olasılık Oranı', 'value': 'ola'},
{'label': 'İnsidans Hızı', 'value': 'hız'}
],
value='eld'
),
])
),
dbc.Col(dbc.Card(sonuc, color="primary", inverse=True)
)],
style={"margin-top": "50px"},
),
),
html.Hr(),
dcc.Location(id='url', refresh=False),
html.Div(id='page-content'),
])
#app.callback([
Output('ustbaslik', 'children'),
Output('ortabaslik', 'children'),
Output('ortamesaj', 'children'),
Output('acik', 'children'),
Output('sonuc', 'children')
],
[
Input('btn-nclicks-1', 'n_clicks'),
Input('btn-nclicks-2', 'n_clicks')
])
def displayClick(btn1, btn2):
changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
if 'btn-nclicks-1' in changed_id:
ustbaslik = 'EPİDEMİYOLOJİK DENEY TASARIMLARI'
ortabaslik = 'Epidemiyolojik Deney Tasarımları'
ortamesaj = 'Epidemiyolojik araştırmalar, hastalıkların ...'
acik = 'Açıklama'
sonuc = 'Araştırma Tasarımınız ...'
elif 'btn-nclicks-2' in changed_id:
ustbaslik = 'EPIDEMIOLOGICAL EXPERIMENT DESIGN'
ortabaslik = 'Theoretical Probability Distributions Software'
ortamesaj = 'Epidemiological research, diseases and ...'
acik = 'Explanation'
sonuc ='Your Research Design ...'
else:
ustbaslik = 'EPİDEMİYOLOJİK DENEY TASARIMLARI'
ortabaslik = 'Epidemiyolojik Deney Tasarımları'
ortamesaj = 'Epidemiyolojik araştırmalar, hastalıkların ...'
acik = 'Açıklama'
sonuc = 'Araştırma Tasarımınız ...'
return ustbaslik,ortabaslik,ortamesaj,acik,sonuc
if __name__ == '__main__':
app.run_server(debug=True)
You need to make a couple of changes. Firstly you need to give your dropdown an id:
dcc.Dropdown(id='dropdown1',
options=[{'label': 'Nitel', 'value': 'nitel'},
{'label': 'Nicel', 'value': 'nicel'}],
value='tur'),
I've given it an id of 'dropdown1'
I also added a container for the output just to show the callback working:
html.Div(id='dd-output-container'),
Then the callback is simply:
#app.callback(
Output('dd-output-container', 'children'),
[Input('dropdown1', 'value')],
)
def dropdown1_callback(v):
return v
Hope this helps. More help can be found here

Create a dash graph with dropdown menu

Hi I have an excel file that looks like this where there are three diferent servers (A, B, C).
I am trying to build a dash app that has a dropdown menu which will make it possible to select the desired server and display the graph for CPU Usage and Memory Usage for each server.
I have tried to modify the following code from the official Dash website. Data can be found on https://plotly.github.io/datasets/country_indicators.csv
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv')
available_indicators = df['Indicator Name'].unique()
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
id='xaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='Fertility rate, total (births per woman)'
),
dcc.RadioItems(
id='xaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
],
style={'width': '48%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='yaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='Life expectancy at birth, total (years)'
),
dcc.RadioItems(
id='yaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
],style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
]),
dcc.Graph(id='indicator-graphic'),
dcc.Slider(
id='year--slider',
min=df['Year'].min(),
max=df['Year'].max(),
value=df['Year'].max(),
marks={str(year): str(year) for year in df['Year'].unique()},
step=None
)
])
#app.callback(
Output('indicator-graphic', 'figure'),
[Input('xaxis-column', 'value'),
Input('yaxis-column', 'value'),
Input('xaxis-type', 'value'),
Input('yaxis-type', 'value'),
Input('year--slider', 'value')])
def update_graph(xaxis_column_name, yaxis_column_name,
xaxis_type, yaxis_type,
year_value):
dff = df[df['Year'] == year_value]
return {
'data': [dict(
x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
mode='markers',
marker={
'size': 15,
'opacity': 0.5,
'line': {'width': 0.5, 'color': 'white'}
}
)],
'layout': dict(
xaxis={
'title': xaxis_column_name,
'type': 'linear' if xaxis_type == 'Linear' else 'log'
},
yaxis={
'title': yaxis_column_name,
'type': 'linear' if yaxis_type == 'Linear' else 'log'
},
margin={'l': 40, 'b': 40, 't': 10, 'r': 0},
hovermode='closest'
)
}
if __name__ == '__main__':
app.run_server(debug=True)
The ouput of this code gives an output similar to mine except that the second drop down menu and the slicer would not be needed
I am struggling to understand how to modify the code to be able to apply to mine. Any help would be welcome. Thank you.
Your callback func will have a single Output and a single Input. The output will be the figure of the graph, and the input will be the value of the dropdown.
In your callback, you can filter the dataframe you build from the Excel file something like this:
df = pandas.read_excel('path/to/my/file.xlsx')
df = df[df['server'].eq(dropdown_value)]
From there just fit the data into the dict that represents the figure much like it's done in the Dash example and return it.

Dash: Graphing from dictionary of dataframes

I have a dictionary, dict_main, of dataframes that I am trying to plot in Dash. I have two dropdowns that allow the user to select firstly the dataframe from within the dictionary, then secondly the columns within those dataframes. This works well and I now want to put the selected columns into a graph and I can't seem to get this working. This is my first time using Dash, sorry if this is obvious. So far I have;
rpm = list(dict_main.keys())
channels = dict_main[rpm[0]]
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],
multi=True,
searchable=False
),
],style={'width': '20%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='channel-dropdown',
multi=True
),
],style={'width': '20%', 'display': 'inline-block'}
),
]
)
#app.callback(
dash.dependencies.Output('channel-dropdown', 'options'),
[dash.dependencies.Input('rpm-dropdown', 'value')]
)
def update_date_dropdown(speed):
return [{'label': i, 'value': i} for i in dict_main[speed]]
if __name__ == '__main__':
app.run_server()
I've tried this;
html.Div([
dcc.Graph(
id='Main-Graph',
figure=go.Figure(
data=[
go.Scatter(
x=rpm, y=channels
)
]
)
),
], style={'width': '98%', 'display': 'inline-block'}
)
With a callback of;
#app.callback(
dash.dependencies.Output('Main-Graph', 'figure'),
[dash.dependencies.Input('channel-dropdown', 'value')])
def updateGraph(channels):
return[{'label': i, 'value': i} for i in dict_main[channels]]
This returns a graph that will not update with a change in dropdown selection. It also appears with a table, which is something I didn't expect. Any help to get this graph working would be really appreciatted. Thanks.
UPDATE:
This works;
rpm = list(dict_main.keys())
channels = dict_main[rpm[0]]
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=False
),
], style={'width': '44%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='channel-dropdown',
multi=True
),
], style={'width': '44%', '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]]
#app.callback(
Output('Main-Graph', 'figure'),
[Input('channel-dropdown', 'value')],
[State('rpm-dropdown', 'value')])
def updateGraph(channels, speed):
if channels:
return go.Figure(data=[go.Scatter(x=dict_main[speed].index, y=dict_main[speed][i]) for i in channels])
else:
return go.Figure(data=[])
if __name__ == '__main__':
app.run_server()
You could do something like this (Dash v1.6.0):
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import json
app = dash.Dash(__name__)
df1 = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
df2 = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
dict_main = {'df1': df1, 'df2': df2}
data = list(dict_main.keys())
channels = dict_main[data[0]]
app.layout = html.Div([
dcc.Graph(id='Main-Graph',
figure=go.Figure(
data=[go.Scatter(x=data, y=channels)]
)),
html.Div([
dcc.Dropdown(
id='data-dropdown',
options=[{'label': label, 'value': label} for label in data],
value=list(dict_main.keys())[0],
multi=False,
searchable=False)],
style={'width': '33%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='x-axis-dropdown',
multi=False)],
style={'width': '33%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='y-axis-dropdown',
multi=False)],
style={'width': '33%', 'display': 'inline-block'}),
])
#app.callback(
[dash.dependencies.Output('x-axis-dropdown', 'options'),
dash.dependencies.Output('y-axis-dropdown', 'options')],
[dash.dependencies.Input('data-dropdown', 'value')]
)
def update_date_dropdown(selected):
if selected:
fields = [{'label': i, 'value': i} for i in dict_main[selected]]
return [fields, fields]
#app.callback(
dash.dependencies.Output('Main-Graph', 'figure'),
[dash.dependencies.Input('data-dropdown', 'value'),
dash.dependencies.Input('x-axis-dropdown', 'value'),
dash.dependencies.Input('y-axis-dropdown', 'value')],
[dash.dependencies.State('Main-Graph', 'figure')])
def updateGraph(df_name, x_field, y_field, data):
source = data['data']
df = dict_main[df_name]
if x_field and y_field and x_field in df.columns and y_field in df.columns:
new_source = [{'x': df[x_field].tolist(), 'y': df[y_field].tolist()}]
source = new_source
return {
'data': source,
'layout': data['layout']
}
if __name__ == '__main__':
app.run_server(debug=True)

How to update xaxis and yaxis name on interval using Dash Plotly in python?

I copy the example from Dash-Plotly multiple inputs (https://dash.plot.ly/getting-started-part-2) and I changed it to be updated on intervals of 2 seconds. The graph is being updated but the title on the X and Y axis are not. The original example updates the X and Y titles on the graph. I am using python 3. I realized that this is happening only because I am using dcc.Graph(id='indicator-graphic', animate=True),. If I use dcc.Graph(id='indicator-graphic'), the xaxis and yaxis are updated but the graph itself no. Here is the code:
import dash
from dash.dependencies import Output, Input, Event
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv(
'https://gist.githubusercontent.com/chriddyp/'
'cb5392c35661370d95f300086accea51/raw/'
'8e0768211f6b747c0db42a9ce9a0937dafcbd8b2/'
'indicators.csv')
available_indicators = df['Indicator Name'].unique()
# load file with all RPi available
available_rpi = pd.read_csv('available_rpi.conf', header=None, dtype={0: str}).set_index(0).squeeze().to_dict()
print("Raspberry Pi's available:")
for key, value in available_rpi.items():
print('IP:{} name: {}'.format(key, value))
print()
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
id='xaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='Fertility rate, total (births per woman)'
),
dcc.RadioItems(
id='xaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
],
style={'width': '30%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='yaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='Life expectancy at birth, total (years)'
),
dcc.RadioItems(
id='yaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
],style={'width': '30%', 'float': 'right', 'display': 'inline-block'})
]),
dcc.Graph(id='indicator-graphic', animate=True),
dcc.Interval(id='graph-update',interval=2*1000),
dcc.Slider(
id='year--slider',
min=df['Year'].min(),
max=df['Year'].max(),
value=df['Year'].max(),
marks={str(year): str(year) for year in df['Year'].unique()}
)
])
#app.callback(
dash.dependencies.Output('indicator-graphic', 'figure'),
[dash.dependencies.Input('xaxis-column', 'value'),
dash.dependencies.Input('yaxis-column', 'value'),
dash.dependencies.Input('xaxis-type', 'value'),
dash.dependencies.Input('yaxis-type', 'value'),
dash.dependencies.Input('year--slider', 'value')],
events=[Event('graph-update', 'interval')])
def update_graph(xaxis_column_name, yaxis_column_name,
xaxis_type, yaxis_type,
year_value):
dff = df[df['Year'] == year_value]
return {
'data': [go.Scatter(
x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
mode='markers',
marker={
'size': 15,
'opacity': 0.5,
'line': {'width': 0.5, 'color': 'white'}
}
)],
'layout': go.Layout(
xaxis={
'title': xaxis_column_name,
'type': 'linear' if xaxis_type == 'Linear' else 'log'
},
yaxis={
'title': yaxis_column_name,
'type': 'linear' if yaxis_type == 'Linear' else 'log'
},
margin={'l': 40, 'b': 40, 't': 10, 'r': 0},
hovermode='closest'
)
}
if __name__ == '__main__':
app.run_server(debug=True)
according to https://community.plot.ly/t/my-callback-is-updating-only-the-lines-of-the-graph-but-not-the-legend/16208/3?u=felipe.o.gutierrez there is a lot of issues with animate=True and they are replacing for Exploring a "Transitions" API for dcc.Graph 2

Categories

Resources