Hi,
Hope you are well.
I would like to have a slider that corresponds to the scatter plot colour bar on my graph. This is to remove outliers of data in the colo bar that can result in an uneven distribution of data. I have populated the slider effectively but have difficulty in getting the colour bar to interact with the slider to determine the range. Any help would be hugely appreciated.
I get the error: ‘Lengths must match to compare’ but unsure of how to resolve it
My code is below:
import base64
import io
from flask import Flask
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import plotly_express as px
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
server = Flask(__name__)
app = dash.Dash(external_stylesheets=external_stylesheets, server=server)
app.layout = html.Div([dcc.Upload(
id='data-table-upload',
children=html.Div([html.Button('Upload File')],
style={'width': '49%', 'height': "60px", 'borderWidth': '1px',
'borderRadius': '5px',
'textAlign': 'center',
}),
multiple=False
),
html.Div([html.Div([html.Div([dcc.Graph(id='my-3D-graph', animate=False)], style={'display': 'inline-block',
'width': '74%',
}),
html.Div([
html.Div([html.Label(
["Select X variable:",
dcc.Dropdown(
id='xaxis-anim-3D',
multi=False,
placeholder="Select an "
"option "
"for X")],
)],
style={
'padding': 10}),
html.Div([html.Label(
["Select Y variable:",
dcc.Dropdown(
id='yaxis-anim-3D',
multi=False,
placeholder='Select an option '
'for Y')],
), ],
style={
'padding': 10}),
html.Div([html.Label(
["Select color variable:",
dcc.Dropdown(
id='caxis-anim-3D',
multi=False,
placeholder='Select an option for color')],
)], style={
'padding': 10}),
html.Div([
html.Label(["Select color bar "
"range:",
dcc.Slider(
id='colorbar-slider',
), ])
], style={'fontSize': 14,
'font-family': 'Arial',
'height': '20%',
'padding': 15,
'width': '90%'})
],
style={
'display': 'inline-block',
'width': '25%',
'float': 'right',
'fontSize': 14,
'font-family': 'Arial',
'backgroundColor': '#ffffff'})
], className='container',
style={'padding': 40,
'backgroundColor': '#ffffff'})])
])
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')))
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:
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
# POPULATE X AXIS DROPDOWN
@app.callback(Output('xaxis-anim-3D', 'options'),
[Input('data-table-upload', 'contents')],
[State('data-table-upload', 'filename')])
def populate_xaxis_dropdown_anim(contents, filename):
df = parse_contents(contents, filename)
return [{'label': i, 'value': i} for i in df.columns]
# POPULATE Y AXIS DROPDOWN
@app.callback(Output('yaxis-anim-3D', 'options'),
[Input('data-table-upload', 'contents')],
[State('data-table-upload', 'filename')])
def populate_yaxis_dropdown_anim(contents, filename):
df = parse_contents(contents, filename)
return [{'label': i, 'value': i} for i in df.columns]
# POPULATE C AXIS DROPDOWN
@app.callback(Output('caxis-anim-3D', 'options'),
[Input('data-table-upload', 'contents')],
[State('data-table-upload', 'filename')])
def populate_saxis_dropdown_anim(contents, filename):
df = parse_contents(contents, filename)
return [{'label': i, 'value': i} for i in df.columns]
# POPULATE COLORBAR SLIDER SCATTER
@app.callback([Output('colorbar-slider', 'min'),
Output('colorbar-slider', 'max'),
Output('colorbar-slider', 'value'),
# Output('colorbar-slider', 'marks')
],
[Input('data-table-upload', 'contents'),
Input('caxis-anim-3D', 'value')],
[State('data-table-upload', 'filename')])
def populate_pressure_slider(contents, caxis, filename):
df = parse_contents(contents, filename)
min = df[caxis].min(),
max = df[caxis].max(),
value = df[caxis].max(),
# marks = {str(pressure): str(pressure) for pressure in df[caxis].unique()}
return min, max, value
# , marks
# @app.callback(Output('caxis-anim-3D','value'),
# [Input('colorbar-slider','value')])
# def range_slider_cb(pressure_value):
# dff = df[df['Pressure'] == pressure_value]
@app.callback(Output('my-3D-graph', 'figure'),
[Input('data-table-upload', 'contents'),
Input('xaxis-anim-3D', 'value'),
Input('yaxis-anim-3D', 'value'),
Input('caxis-anim-3D', 'value'),
Input('colorbar-slider', 'value')],
[State('data-table-upload', 'filename')]
)
def update_figure(contents, x, y, caxis, color_value, filename):
df = parse_contents(contents, filename)
dff = df[df[caxis] == color_value]
return px.scatter(dff, x=dff[x], y=dff[y], title="", animation_frame="Pressure",
animation_group=dff.columns[0],
hover_name=dff.columns[0],
hover_data={}, template="none", color=dff[caxis],
color_continuous_scale='Viridis',
).update_xaxes(showgrid=False, title=x, autorange=True, ticks='outside',
showline=True, showspikes=True, spikethickness=1, spikedash='solid',
mirror=True, tickformat=".1f").update_yaxes(spikedash='solid',
showgrid=False,
title=dict(text=y,
standoff=5),
autorange=True, ticks='outside',
showspikes=True, spikethickness=1,
showline=True, mirror=True,
tickformat=".1f").update_layout(
clickmode='event+select', hovermode='closest', margin={'l': 80}, autosize=True, font=dict(family='Helvetica',
),
coloraxis_colorbar=dict(title=dict(text=caxis, side='right'), ypad=0),
).update_traces(marker=dict(size=10,
opacity=0.7,
showscale=False,
line=dict(width=0.7, color='DarkSlateGrey'),
colorscale="Viridis"))
if __name__ == '__main__':
app.run_server()
My datasheet can be accessed via this link.