How Dynamically populate the DropDown from the data uploaded through Plotly Dash dcc upload option - plotly-dash

I have uploaded the data using Plotly Dash dcc upload option. I am not able to dynamically populated the unique columns of uploaded dataframe as part of DropDown
I am able to successfuly upload the file using dcc upload option; i am able to see the output in dash table. but using same input, i am not able to see the output from dropdown.
the dataframe, i have uploaded with the columns of (country, continent, population)
i should able to get the unique columns dropdown
this is my code:
import base64
import datetime
import io
import plotly.graph_objs as go
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_table
import dash_table_experiments as dte
from dash.dependencies import Input, Output, State
import pandas as pd
app = dash.Dash()
app.layout = html.Div([
html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
multiple=True
),
html.Div(id='output-data-upload'),
])
dcc.Tab(label='Discrete Info', children=[
html.Div([
dcc.Dropdown(
id='select_column',
),
]),
html.Div([
dcc.Graph(
id='bar1',
hoverData={'points': [{'customdata': ''}]},
)
], style={'width': '100%', 'display': 'inline-block', 'padding': '0 10'}),
]),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
#app.callback(Output('output-data-upload', 'children'),
[Input('upload-data', 'contents')],
[State('upload-data', 'filename'),
State('upload-data', 'last_modified')])
def update_output (list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
#app.callback(Output('select_column', 'options'
[Input('output-data-upload', 'children'')]
def dd_update (options)
return(options)

This is a little tricky without specific code to reference, but the basic idea is to set up a callback that will update the options prop of your dcc.Dropdown. You can have that callback triggered (Input) by the upload, make it read in the dataframe, obtain the columns, and then output the properly formatted list of dictionaries.

Please use a following simple example that solves your problem
import base64
import io
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from dash.dependencies import Input, Output
app = dash.Dash()
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
),
dcc.Dropdown(
id='dropdown',
options=[],
value=None),
])
def parse_data(contents, filename):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV or TXT file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
elif 'txt' or 'tsv' in filename:
# Assume that the user upl, delimiter = r'\s+'oaded an excel file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')), delimiter = r'\s+')
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return df
#app.callback(
Output('dropdown', 'options'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename')])
def update_options(contents, filename):
if contents:
df = parse_data(contents, filename)
df = df.set_index(df.columns[0])
lst = [{'label': i, 'value': i} for i in df.columns]
return lst
else:
return []
if __name__ == '__main__':
app.run_server(debug=True)

Here is my working code, very basic, that you can use as a reference
html.Div(children=[
html.Div(children=[
dcc.Dropdown(id='dropdown_students_cols', options=[{'label': i, 'value': i} for i in list(filter(lambda x: x!='userid', list(df)))], value='component'),
]),
html.Div(children=[
dcc.Dropdown(id='dropdown_row_names'),
]),
])
#app.callback(
Output(component_id='dropdown_row_names', component_property='options'),
[Input(component_id='dropdown_students_cols', component_property='value')],)
def get_row_names(column_name='component'):
row_names = df[column_name].unique().tolist()
lst = [{'label': i, 'value': i} for i in row_names]
print(lst)
return lst
The print statement in the callback returns a list of dictionaries that I can use for options:
[{'label': 'mod_glossary', 'value': 'mod_glossary'}, {'label': 'mod_quiz', 'value': 'mod_quiz'},...]
Don't pay attention to lambda function in the original dropdown id='dropdown_students_cols', I just needed to exclude this column from selection.
When you make selection in the original dropdown id='dropdown_students_cols', it invokes the callback function with the selection as an argument.
This selection gives me a required column in the df and then I build a list of unique rows in this column.
Then I iterate over this list to build a list of dictionaries with label:value
The print statement confirms that the list is built successfully
Then I return that list as options for the child dropdown id='dropdown_row_names'
So you can use another trigger as Input, in your case Upload, pass values into the callback, process the data as you need and then return a list if dictionaries as options for the dropdown.
I suggest you trim your code to a vary basic working example and then slowly build up from it.

Related

dash dcc.Uploader not working in multipage app

0
I have a multi-page dash app for generating custom dashboards based on user submission. I'm trying to create a secondary page for uploading files. The problem is that the dcc.Upload or the callback function does not produce the expected behavior, that is: a html.Div that shows the uploaded data.
This is my secondary page, organized in tabs:
import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
import dash_mantine_components as dmc
from dash import dash_table
from dash.exceptions import PreventUpdate
import os
import unicodedata
import requests
from bs4 import BeautifulSoup
from urllib.request import urlopen
from urllib.parse import quote as urlquote
import sqlite3
from dash_iconify import DashIconify
from dash.dependencies import Input, Output, State
import pandas as pd
from app import app
def layout():
return [
dmc.Tabs(
[
dmc.TabsList(
[
dmc.Tab("Import", value="import"),
dmc.Tab("Connect BD", value="connectbd"),
dmc.Tab("Explore", value="explore"),
]
),
dmc.TabsPanel(
html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '260px',
'lineHeight': '60px',
'borderWidth': '1px',
#'borderStyle': 'dashed',
'background' : '#f8f9fa',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True,
),
html.Div(id='output-data-upload'),
]),
value="import"),
dmc.TabsPanel("Settings tab content", value="connectbd"),
dmc.TabsPanel("Settings tab content", value="explore"),
],
#color="black",
orientation="horizontal",
)
]
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
#app.callback(Output('output-data-upload', 'children'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
Solution attempts: the example of the dcc.Upload is in the documentation , but I use it inside a tab inside a secondary page that is called with the layout function in the app.py. The example is working correctly when is run as it is implemented in the documentation, but I can´t adapt it to my specific use case. I think the problem is near the callback or in the function that outputs the table.
I´m a newbie in dash. Thanks in advance for any help.
Expted: html.Div with uploaded data.

In Dash Plotly how do I upload CSV with dcc.Upload to store using dcc.Store and then display table?

haven’t found a good answer to this issue I am having. Please help!
My goal is to upload CSV via dcc.Upload, store it in dcc.Store, and then display table.
I am taking the code from dcc.Upload tutorial here and inserting a dcc.Store component. The goal is to have two callbacks. The first one would have upload data as input and store as output. The second callback would take store as input and output to a html.Div.
See the code below that is not working. Please help!
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html, dash_table
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
dcc.Store(id='store'),
html.Div(id='output-data-upload'),
])
#Goal here is to store the csv from upload into dcc.Store
#app.callback(Output('store', 'data'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(contents, list_of_names, list_of_dates):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
return df.to_json(date_format='iso', orient='split') #I have to convert to json format to store in dcc.Store
#Goal here is to then extract dataframe from dcc.store by reading json and output a table
#app.callback(
Output('output-data-upload', 'children'),
Input('store', 'data')
)
def output_from_store(stored_data):
df = pd.read_json(stored_data, orient='split')
return html.Div([
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
])
if __name__ == '__main__':
app.run_server()
I followed the dcc.Upload tutorial and tried inserting the dcc.Store into it.
Your code was missing a few adjustments to run as expected.
First, as sometimes the values can be inside a list you need to get only the value inside the list, in this case, it's in index 0.
content_string = contents[0].split(',')
Second, to avoid some warnings I have added a condition that will not run the element if the upload values are empty.
if [contents, list_of_names, list_of_dates] == [None, None, None]:
return dash.no_update
You can also use it in your callback declaration:
prevent_initial_call=True
And as a tip, I would suggest you use debug=True n your development environment, so you can have better feedback about what's going wrong, making it easier to debug your code to fix the error
app.run_server(debug=True)
Full code based on your example:
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html, dash_table
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
dcc.Store(id='store'),
html.Div(id='output-data-upload'),
])
import dash
#Goal here is to store the csv from upload into dcc.Store
#app.callback(Output('store', 'data'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'),
prevent_initial_call=True)
def update_output(contents, list_of_names, list_of_dates):
if [contents, list_of_names, list_of_dates] == [None, None, None]:
return dash.no_update
content_type, content_string = contents[0].split(',')
decoded = base64.b64decode(content_string)
df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
return df.to_json(date_format='iso', orient='split') #I have to convert to json format to store in dcc.Store
#Goal here is to then extract dataframe from dcc.store by reading json and output a table
#app.callback(
Output('output-data-upload', 'children'),
Input('store', 'data'),
prevent_initial_call=True
)
def output_from_store(stored_data):
df = pd.read_json(stored_data, orient='split')
return html.Div([
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
])
if __name__ == '__main__':
app.run_server(debug=True)
I hope it can be helpful for you.
Regards,
Leonardo

Error 'An object was provided as `children` instead of a component....' appears on dashboard

sample csv data:
date,Data Center,Customer,companyID,source,target,value
I run below code for put the sankey chart in dashboard, and the chart can be updated accordingly by applying filters. but an error appears on dashboard. What is the issue?
An object was provided as children instead of a component, string,
or number (or list of those). Check the children property that looks
something like:
import io
from base64 import b64encode
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import plotly.io as pio
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
colors = {
'background': '#111111',
'text': '#7FDBFF'
}
dataset = pd.read_csv('leanSankey.csv')
labelListTemp1 = list(set(dataset.source.values))
labelListTemp2 = list(set(dataset.target.values))
labelList = labelListTemp1 + labelListTemp2
sankey_node = list(dict.fromkeys(labelList))
fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=20,line = dict(color = "black", width = 0.5),label = labelList,color = 'black' ),
link = dict(source = dataset.source.apply(lambda x: labelList.index(x)),
target = dataset.target.apply(lambda x: labelList.index(x)),
value = dataset.value))])
#fig.update_layout(autosize=False,width = 3000,height = 1000,hovermode = 'x',title="test user behavior monitor",font=dict(size=16, color='blue'))
#fig.write_html('test.html', auto_open=True)
#fig.show()
app.layout = html.Div([
dcc.Dropdown(
id='dataCenter_dropdown',
options=[ {'label': i, 'value': i} for i in dataset['Data Center'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select Data Center'),
dcc.Dropdown(
id='customer_dropdown',
options=[{'label': i, 'value': i} for i in dataset['Customer'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select Customer'),
dcc.Dropdown(
id='companyID_dropdown',
options=[{'label': i, 'value': i} for i in dataset['companyID'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select companyID'),
# html.Div(id='dd-output-container'),
dcc.Graph(id='uxrPerfGoalSankey',figure=fig)
])
#app.callback(
# Output('dd-output-container', 'children'),
Output('uxrPerfGoalSankey', 'figure'),
[Input('dataCenter_dropdown', 'value'),
Input('customer_dropdown', 'value'),
Input('companyID_dropdown', 'value')])
def update_graph(dataCenter, customer, companyID):
if dataCenter=='Select all' and customer=='Select all' and companyID=='Select all':
df=dataset.copy()
else:
df = dataset.loc[dataset['Data Center'].isin([dataCenter]) & dataset['Customer'].isin([customer]) & dataset['companyID'].isin([companyID])]
labelListTemp1 = list(set(df.source.values))
labelListTemp2 = list(set(df.target.values))
labelList = labelListTemp1 + labelListTemp2
sankey_node = list(dict.fromkeys(labelList))
fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=20,line = dict(color = "black", width = 0.5),label = labelList,color = "blue" ),
link = dict(source = df.source.apply(lambda x: labelList.index(x)),
target = df.target.apply(lambda x: labelList.index(x)),
value = df.value))])
return fig
if __name__ == '__main__':
app.run_server(debug=True)
Your callback function returns a figure and is trying to assign it to the children property of a html.Div. Can't do that as far as I know. A div's child should be other components, strings or numbers as stated in the error message.
Did you mean to write
Output('uxrPerfGoalSankey', 'figure'),
instead?
If not and you need to return a new fig to that div, create a dcc.Graph inside your div and return that graphs's figure value instead.
Edit:
You also overwrite your input values right at the top of your callback function. No matter what you select, the df is ultimately filtered by the same values. I.E. you select dataCenter 'A' in your dropdown but in the first line you set dataCenter to dataframe['Data Center'], so what was the point of selecting one? If that's not intended, delete those assignments?
One imminent pitfall by the way: multi dropdowns pass either a single value or a list of values. To make your df selection consistent, force all the inputs to be lists:
if not isinstance(dataCenter, list):
dataCenter = [dataCenter]
# etc
Edit 2:
The issue was how you handle the parameters being lists vs single values and the selection of 'select all'. I adjusted the logic to treat 'None' (dd selection empty) and 'Select all' as all values selected. If you don't want to plot anything when a selection is empty, do this instead:
from dash.exceptions import PreventUpdate
...
And then first thing in your callback function:
if dataCenter is None or customer is None or companyID is None:
raise PreventUpdate
Anyway here's the code with the logic as I described it:
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objects as go
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
colors = {
'background': '#111111',
'text': '#7FDBFF'
}
dataset = pd.read_csv('values.csv')
def generate_graph(df):
labels = list(set(df.source.values)) + list(set(df.target.values))
fig = go.Figure(data=[
go.Sankey(node=dict(pad=15, thickness=20, line=dict(color="black", width=0.5), label=labels, color="blue"),
link=dict(source=df.source.apply(lambda x: labels.index(x)),
target=df.target.apply(lambda x: labels.index(x)),
value=df.value))
])
return fig
app.layout = html.Div([
dcc.Dropdown(
id='dataCenter_dropdown',
options=[{'label': i, 'value': i} for i in dataset['Data Center'].unique()] + [
{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select Data Center'),
dcc.Dropdown(
id='customer_dropdown',
options=[{'label': i, 'value': i} for i in dataset['Customer'].unique()] + [
{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select Customer'),
dcc.Dropdown(
id='companyID_dropdown',
options=[{'label': i, 'value': i} for i in dataset['companyID'].unique()] + [
{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select companyID'),
dcc.Graph(id='uxrPerfGoalSankey', figure=generate_graph(dataset))
])
#app.callback(
Output('uxrPerfGoalSankey', 'figure'),
[Input('dataCenter_dropdown', 'value'),
Input('customer_dropdown', 'value'),
Input('companyID_dropdown', 'value')])
def update_graph(dataCenter, customer, companyID):
if dataCenter is None or len(dataCenter) == 0 or 'allID' in dataCenter:
dataCenter = dataset['Data Center']
elif not isinstance(dataCenter, list):
dataCenter = [dataCenter]
if customer is None or len(customer) == 0 or 'allID' in customer:
customer = dataset['Customer']
elif not isinstance(customer, list):
customer = [customer]
if companyID is None or len(companyID) == 0 or 'allID' in companyID:
companyID = dataset['companyID']
elif not isinstance(companyID, list):
companyID = [companyID]
df = dataset[
(dataset['Data Center'].isin(dataCenter)) &
(dataset['Customer'].isin(customer)) &
(dataset['companyID'].isin(companyID))
]
return generate_graph(df)
if __name__ == '__main__':
app.run_server(debug=True)
Runs fine for me, let me know if any other issues arise.

Dash plotly Datatable column filtering or cropping

I have implemented a live-update datatable to correspond with a live-update graph. Functionally, both work very well. I do have a problem with filtering the datatable to include certain columns and exclude others. For ex. If the graph is zoomed in for certain x-value (09:00-10:00), is there any way I can also crop the corresponding datatable to represent columns from that same value? Perhaps add a button with a callback that deletes specific column ids? Is there a way to delete specific 'column' 'id' inputs through python with out using the GUI? As of now, I can only manually delete individual columns which is very tedious given the amount of columns. Thank you. I hope this question is not too open-ended.
table_contents = ['Propofol/Remi # 6.5 ug/ml', 'Fentanyl (ug)', 'Propofol (mg)', 'Remi (ug)',
'Ketorolac (mg)']
html.Div([dash_table.DataTable(
id='editing-columns',
columns=[{
'name': 'Parameter',
'id': 'column1',
'deletable': True,
'renamable': True
}],
data=[
{'column1': j}
for j in table_contents
],
editable=True,
)]),
# The callback stores the previous length of the csv file in dcc.store and appends new columns if new csv data uploaded
#app.callback(Output('editing-columns', 'columns'),
[Input('graph-update', 'n_intervals')],
[State('editing-columns', 'columns')],
[State('mystore', 'data')])
def update_columns(n, btn, existing_columns, data):
with open('temp.csv', 'r') as rf:
reader = csv.reader(rf)
for a in reader:
existing_columns.append({
'id': a[3], 'name': a[3],
'renamable': True, 'deletable': True
})
return existing_columns, html.Div('Program running')
else:
check_length = []
de_serialized = json.loads(data)
with open('temp.csv', 'r') as rf:
reader = csv.reader(rf)
for a in reader:
check_length.append(a[3])
if len(check_length) == 0:
return existing_columns, html.Div('Program running')
elif len(check_length) > len(de_serialized):
existing_columns.append({
'id': check_length[-1], 'name': check_length[-1],
'renamable': True, 'deletable': True
})
return existing_columns, html.Div('Program running')
else:
return existing_columns, html.Div('Program running')
#The graph is a bar and scatter graph that is updated with x,y values derived from the same csv as the datatable.
#app.callback(
dash.dependencies.Output('live-graph', 'figure'),
[dash.dependencies.Input('graph-update-BP', 'n_intervals')],
)
def update_graph_scatter_1(btn, n):
trace = []
trace2 = []
blood_pressure = []
hr = []
with open('temp.csv', 'r') as rf:
reader_2 = csv.reader(rf)
for a in reader_2:
blood_pressure.append(eval(a[4]))
time.append(a[3])
for i in range(0, len(blood_pressure)):
trace.append(go.Box(y=blood_pressure[i],
x=triple_time[i],
line=dict(color='#6a92ff'),
hoverinfo='all'))
for a in range(0, len(hr)):
trace2.append(go.Scatter(y=coated_hr[a],
x=coated_time[a],
name='HR',
Whenever you pan or zoom, a relayoutData interaction is triggered, from there you can get the axis ranges.
The dcc.Graph component has four attributes that can change through
user-interaction: hoverData, clickData, selectedData, relayoutData.
These properties update when you hover over points, click on points,
or select regions of points in a graph.
https://dash.plotly.com/interactive-graphing
import json
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
import plotly.express as px
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.DataFrame({
"x": [1,2,1,2],
"y": [1,2,3,4],
"customdata": [1,2,3,4],
"fruit": ["apple", "apple", "orange", "orange"]
})
fig = px.scatter(df, x="x", y="y", color="fruit", custom_data=["customdata"])
fig.update_traces(marker_size=20)
app.layout = html.Div([
dcc.Graph(
id='basic-interactions',
figure=fig
),
html.Div(className='row', children=[
html.Div([
dcc.Markdown("""
**Zoom and Relayout Data**
Click and drag on the graph to zoom or click on the zoom
buttons in the graph's menu bar.
Clicking on legend items will also fire
this event.
"""),
html.Pre(id='relayout-data'),
])
])
])
#app.callback(
Output('relayout-data', 'children'),
Input('basic-interactions', 'relayoutData'))
def display_relayout_data(relayoutData):
if relayoutData is None:
raise PreventUpdate
elif "xaxis.range[0]" not in relayoutData.keys():
raise PreventUpdate
else:
#get the relevant axis ranges, you can use to drop columns from the datatable
print(relayoutData,type(relayoutData))
return json.dumps(relayoutData, indent=2)
if __name__ == '__main__':
app.run_server(debug=True)

plotly dash: How to get headline of csv as options for dropdown

I am writing a dash-app.
At the moment my app looks like this
`
import base64
import io
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import matplotlib.pyplot
from dash.dependencies import Input, Output
import dash_table_experiments as dt
import numpy as np
app = dash.Dash()
app.scripts.config.serve_locally = True
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
#plot dropdowns graph and tabel
html.Div(id='output-data-upload'),
html.Div(dt.DataTable(rows=[{}]), style={'display': 'none'}),
],
)
#%%methodes
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')),sep=';',header=6)
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded),sep=';',header=6)
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
available_indicators=list(df)
ind =np.delete(available_indicators,0),
print (ind)
return html.Div([
#x-Achse
html.Div('Choose Data for x-axis'),
dcc.RadioItems(
id='x_Achse',
options=[
{'label': i, 'value': i} for i in ind[0]],
),
#y-Achse
html.Label('Choose Data for y-axis'),
dcc.Dropdown(
id='y-Achse',
options=[
{'label': i, 'value': i}for i in ind[0]],
multi= True
),
#Graph
return_graph(df,1,1),
html.H5(filename),
# Use the DataTable prototype component:
# github.com/plotly/dash-table-experiments
dt.DataTable(rows=df.to_dict('records')),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
#%%
def return_graph(df, x_Werte, Y_Werte_Array):
return dcc.Graph(id='Liniendiagramm',
figure={
'data': [go.Scatter(
x=df['Date/Time'], #change to x_Werte
y=df['Var_01'], #change to Y_Werte_Array[0]
text=df['Var_01'], #change to Y_Werte_Array[0]
name='Var_01' #change to Y_Werte_Array[0]
),
go.Scatter(
x=df['Date/Time'], #change to x_Werte
y=df['Var_02'], #change to Y_Werte_Array[1]
text=df['Var_02'], #change to Y_Werte_Array[1]
name='Var_02' #change to Y_Werte_Array[1]
),
]
}
)
#%%
#end Methoden
#%%callback
#app.callback(Output('output-data-upload', 'children'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename'),
Input('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d,) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
#%%
if __name__ == '__main__':
app.run_server(debug=True)`
Now my Problem.
The dropdowns in my app are in the methode parse_contents. So I get an error, if I try to use a callback to get the value of the dropdowns. The options for the dropdowns are calculate amongst other things in this methode.
I need a solution to get the headline of a Tabel in a .csv flie. Use the values of the headline as options for the dropdowns and write the selected Values of the dropdowns in the methode return_graph .
Finaly it's has to look so
enter image description here
but at the moment the both dropdowns are useless and the graph is ploted by static values
Sorry for the german words in the code, and the bad english.
So now I have a solution for my problem. If Someone want to use it, here is the code. Please note, that in the methode "parse content" the parameters sep=';' and header=6 lines, are set as static parameters.
`import base64
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import dash_table_experiments as dte
from dash.dependencies import Input, Output
import dash
import pandas as pd
import io
app = dash.Dash()
app.scripts.config.serve_locally = True
app.config['suppress_callback_exceptions'] = True
app.layout = html.Div([
html.H5("Upload Files"),
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
),
html.Br(),
html.Div("X_Achse"),
dcc.Dropdown(id='x_Achse',
multi = False,
placeholder='Filter Column'),
html.Div('Y_Werte'),
dcc.Dropdown(id='y_Achse',
multi = True,
placeholder='Filter Column'),
html.Div(id='graph'),
html.Br(),
html.H5("Updated Table"),
html.Div(dte.DataTable(rows=[{}], id='table'))
])
# Functions
#%%
# file upload function
def parse_contents(contents, filename):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')),sep=';',header=6)
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded),sep=';',header=6)
except Exception as e:
print(e)
return None
return df
#%%
def return_graph(df, x_Werte, Y_Werte_Array):
return dcc.Graph(id='Liniendiagramm',
figure={
'data': [ #definiert die Daten welche visualisiert werden sollen
go.Scatter(
x=df[x_Werte],
y=df[Y_Werte_Array[i]],
text=df[Y_Werte_Array[i]],
name=Y_Werte_Array[i]
)
for i in range(0,len(Y_Werte_Array))
]
}
)
#%%
#app.callback(Output('graph','children'),
[Input('x_Achse','value'),
Input('y_Achse','value'),
Input('table','rows')])
def update_graph(x,y,c):
if x and y and c is not None:
print (x)
print (y)
# print (c)
dff = pd.DataFrame.from_dict(c)
# print('anfang')
# print(dff)
# print ('ende')
graph1=return_graph(dff,x,y)
# print (c)
return graph1 #return_graph(c,a,b)
#%%
# callback table creation
#app.callback(Output('table', 'rows'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename')])
def update_output(contents, filename):
if contents is not None:
df = parse_contents(contents, filename)
if df is not None:
# print (df)
return df.to_dict('records')
else:
return [{}]
else:
return [{}]
#%%
#callback update options of filter dropdown
#app.callback(Output('x_Achse', 'options'),
[Input('table', 'rows')])
def update_x_Achse( tablerows):
if tablerows is not None:
dff = pd.DataFrame(tablerows) # <- problem! dff stays empty even though table was uploaded
print ("updating... dff empty?:"), dff.empty #result is True, labels stay empty
return [{'label': i, 'value': i} for i in sorted(list(dff))]
#%%
#app.callback(Output('y_Achse', 'options'),
[Input('table', 'rows')])
def update_y_Achse( tablerows):
if tablerows is not None:
dff = pd.DataFrame(tablerows) # <- problem! dff stays empty even though table was uploaded
print ("updating... dff empty?:"), dff.empty #result is True, labels stay empty
return [{'label': i, 'value': i} for i in sorted(list(dff))]
#%%
app.css.append_css({
"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})
if __name__ == '__main__':
app.run_server(debug=True)`