Black Lives Matter. Please consider donating to Black Girls Code today.

Interactive Graphing ClickData updates data from slider

Hi there,
I have got ClickData working using the Dash tutorial below:
https://dash.plot.ly/interactive-graphing
I was wondering if there is any way where the data on the click data can update itself when there is a slider.
Say there is a slider with values 1,2,3 and when on 1 you click a data point. Is it possible for the click data to update the data for that point as you move to values 2 and 3 on the slider?
Any help regarding this would be much appreciated.
Best,
Tilly

Hi Tilly,
I think this is possible but I’m not 100% sure what you’re trying to do.

If a user clicks on point value 1 on a slider, what data would you like that click to influence?

Hi Adam,
Thanks for the response!
If we take the plotly gap minder slider bubble plot as an example:


I have recreated a similar plot (however without the play/pause button) and also a clickData component that shows the value of the bubble being selected. I was wondering if it were possible for the data of the bubble selected to change on the click data screen according to the value on the slider. Say the x/y values for China in 1952 will be different to 1962.
Hope I have made that clearer.

I tried to include a callback of the following:

@app.callback(
    Output('click-data', 'children'),
    [Input('plot-id', 'clickData'),
     Input('year-slider', 'value')])
def display_click_data(clickData, slider_value):
    dff = df[df['Year'] == slider_value]
    return dff[json.dumps(clickData, indent=2)]

But was unsuccessful.
Thanks!

I’m not too sure, actually. Would it work if you did two separate callbacks? One for the slider to update the figure/plot and the second one for the figure to update the click-data. For example:

@app.callback(
    Output('plot-id', 'figure'),
    [Input('year-slider', 'value')])

@app.callback(
    Output('click-data', 'children'),
    [Input('plot-id', 'clickData')])

Hi,
Thanks!
I tried that but it did not work. I get an error as there is already a callback assigned to the output (i.e. plotting the scatter for each year).

Do you want to try to post the whole code (or maybe an abbreviated version of your code) so we can play around with it and help you find the solution? I think what you’re trying to do is possible.

Hi,
I have shortened my current code below. I am also having trouble with rescaling my animation - I have to use auto-scale for the animation to rescale instead of it automatically doing so. Forum posts said that ‘Animate=False’ should do the trick however it did not work for me. Any advice on how to tackle that as well would be great.
To the main problem - as you can see the data of the clicked point is not varying as the slider progresses and I am having trouble linking clickData to the slider using a callback.

import plotly.express as px
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import flask
import json
from textwrap import dedent as d

server = flask.Flask(__name__)
app = dash.Dash(__name__, server=server)

dataset = pd.read_csv('/Users/mythilisutharson/documents/cam_work/mof_explorer_flourish/MOF_trans_data_bad_edit.csv')
col_options = [dict(label=x, value=x) for x in dataset.columns]
features = dataset.columns

styles = {
    'pre': {}
}
tabs_styles = {}
tab_style = {}

tab_selected_style = {}

dimensions = ['select x variable', 'select y variable ', 'select color variable', 'select size variable']
app.layout = html.Div([html.H1("", style={}),
                       html.Div(" ", style={}),
                       html.Div([dcc.Graph(id="graph", animate=False,
                                           ), html.Div([
                           dcc.Markdown(d("""
                                ***Click Data
                                Click on points in the graph.
                                """)),
                           html.Pre(id='click-data', style=styles['pre']),
                       ], style={}
                       )

                                 ], style={}),
                       html.Div(
                           [
                               html.P([d + ":", dcc.Dropdown(id=d,
                                                             options=[{'label': i, 'value': i} for i in features
                                                                      ])])
                               for d in dimensions

                           ],
                           style={},

                       ),

                       ], style={})


@app.callback(Output('click-data', 'children'),
              [Input('graph', 'clickData'),
               ])
def display_click_data(clickData):
    return json.dumps(clickData, indent=2)


@app.callback(Output("graph", "figure"), [Input(d, "value") for d in dimensions])
def make_figure(x, y, color, size):
    return px.scatter(dataset, x=x, y=y, title="MOF Explorer", animation_frame="Pressure",
                      animation_group="DDEC Code", size=size, color=color,
                      hover_name="DDEC Code", color_continuous_scale='Viridis',
                      hover_data={"DDEC Code", "Density", "Void Fraction"},

                      ).update_xaxes(showgrid=False, title=x).update_yaxes(showgrid=False, title=y).update_layout(
        clickmode='event+select', hovermode='closest', margin={'l': 50, 'b': 80, 't': 50, 'r': 10}
    )


app.run_server(debug=True)

Thank you!

Tilly,
Unfortunately, I can’t replicate your code because I don’t have access to your csv file. If you are able to share a link to the csv file, or at least a smaller version with a few of the rows, I might be more helpful.

One thing I am seeing in your code that could be affecting your problem is the order of the functions.

You are calling the click-data from the graph before you have even built the graph. Your function to “def make_figure(x, y, color, size)” and its respective callback should probably come before your function to “display_click_data” from a graph that has not been created yet.

I’m not sure this will solve the problem, but I’m happy to look deeper into it.

Hi Adam,
Apologies, the csv can be accessed with this link.


I rearranged the code and used the callbacks that you and I previously suggested and it was still unsuccessful.

Hi Tilly,
As I change the dropdown options, the click-data also changes. Is that what you wanted?

Hi Adam,
Similar but I wanted the click data to change as you move across the slider. Thanks so much!

I’m not sure how to do that or if Dash allows that. Because you’re asking the clickdata to update itself without being clicked on scatter plot; you want the clickdata children to update itself just by changing the slider. But the slider can only update the scatter plot. I don’t think a slider value can update a clicked data point if the data point has not been clicked.

Can anyone else in the Dash community help Tilly, please.

Hi Adam,
No worries, thank you for your help regardless!
Best, Tilly