Is there a way to add symbols to the cross filtering plotly tutorial without having to deal with different curveNumbers? The problem I am dealing with is that when I select points in one plot it will highlight those selected point numbers from all curveNumbers. So for example if I just select point 2, it will highlight point 2 and point 3 because both have the same point number, (different curveNumbers).
Here is some example code:
from dash import Dash, dcc, html
import numpy as np
import pandas as pd
from dash.dependencies import Input, Output
import plotly.express as px
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = Dash(__name__, external_stylesheets=external_stylesheets)
# make a sample data frame with 6 columns
np.random.seed(0) # no-display
df = pd.DataFrame({"Col " + str(i+1): np.random.rand(30) for i in range(6)})
df['is_even'] = df.index % 2 == 0
df['color'] = df.index % 4
app.layout = html.Div([
html.Div(
dcc.Graph(id='g1', config={'displayModeBar': False}),
className='four columns'
),
html.Div(
dcc.Graph(id='g2', config={'displayModeBar': False}),
className='four columns'
),
html.Div(
dcc.Graph(id='g3', config={'displayModeBar': False}),
className='four columns'
)
], className='row')
def get_figure(df, x_col, y_col, selectedpoints, selectedpoints_local):
if selectedpoints_local:
if selectedpoints_local['range']:
ranges = selectedpoints_local['range']
selection_bounds = {'x0': ranges['x'][0], 'x1': ranges['x'][1],
'y0': ranges['y'][0], 'y1': ranges['y'][1]}
else:
selection_bounds = {'x0': np.min(df[x_col]), 'x1': np.max(df[x_col]),
'y0': np.min(df[y_col]), 'y1': np.max(df[y_col])}
else:
selection_bounds = {'x0': np.min(df[x_col]), 'x1': np.max(df[x_col]),
'y0': np.min(df[y_col]), 'y1': np.max(df[y_col])}
# set which points are selected with the `selectedpoints` property
# and style those points with the `selected` and `unselected`
# attribute. see
# https://medium.com/@plotlygraphs/notes-from-the-latest-plotly-js-release-b035a5b43e21
# for an explanation
fig = px.scatter(df, x=df[x_col], y=df[y_col], text=df.index, symbol = df['is_even'])
fig.update_traces(selectedpoints=selectedpoints,
customdata=df.index,
mode='markers+text', marker={ 'color': 'rgba(0, 116, 217, 0.7)', 'size': 20 }, unselected={'marker': { 'opacity': 0.3 }, 'textfont': { 'color': 'rgba(0, 0, 0, 0)' } })
fig.update_layout(margin={'l': 20, 'r': 0, 'b': 15, 't': 5}, dragmode='select', hovermode=False)
fig.add_shape(dict({'type': 'rect',
'line': { 'width': 1, 'dash': 'dot', 'color': 'darkgrey' } },
**selection_bounds))
return fig
# this callback defines 3 figures
# as a function of the intersection of their 3 selections
@app.callback(
Output('g1', 'figure'),
Output('g2', 'figure'),
Output('g3', 'figure'),
Input('g1', 'selectedData'),
Input('g2', 'selectedData'),
Input('g3', 'selectedData')
)
def callback(selection1, selection2, selection3):
selectedpoints = df.index
for selected_data in [selection1, selection2, selection3]:
if selected_data and selected_data['points']:
selectedpoints = np.intersect1d(selectedpoints,
[p['customdata'] for p in selected_data['points']])
return [get_figure(df, "Col 1", "Col 2", selectedpoints, selection1),
get_figure(df, "Col 3", "Col 4", selectedpoints, selection2),
get_figure(df, "Col 5", "Col 6", selectedpoints, selection3)]
if __name__ == '__main__':
app.run_server(debug=True)
** Note, that I am using an old version of dash (dash=2.6.0) because this tutorial doesn’t currently work in newer versions.