Display click data on multiple graphs

I have multiple bar plots. I want to display data after every click on the bar. I am able to plot graphs but unable to get the clickData.

Hi @dashapp, welcome to the community!
You’re gonna need to use callbacks to add interactivity to your bar plots.
You can find the (extensive) documentation here.

Also if you share your code so far the community could better help you.

1 Like

imI have used pattern matching call backs for getting the click data to display the data table but i am unable to get the output

@dashapp would you be able to share your code? That way I might be able to better help you.

This is a sample file i’m working on large data file. So I am appending my bar plots in output variable using different columns data. I want to generate the click data when a user clicks on the plot and update other data when the user clicks on other plot. let me know if other approach is there.

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from dash.dependencies import Input, Output, ALL, State, MATCH, ALLSMALLER

import dash
from dash import Dash, html, dcc, Output, Input, callback, dash_table
import dash_bootstrap_components as dbc


from dash.dependencies import Input, Output, State
from jupyter_dash import JupyterDash
#app = JupyterDash(__name__)


app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP],
                meta_tags=[{'name': 'viewport',
                            'content': 'width=device-width, initial-scale=1.0'}]
                )
https://data.world/makeovermonday/2018w48
df=read_csv(r'https://data.world/makeovermonday/2018w48')
for var in df.city.unique()  
 
  d1=df.loc[df.city==var]
  fig = px.bar(d1, x="city", y="cost", barmode="group",
             )
  output.append(dcc.Graph(id={'type': 'dynamic-graph','index': var },figure=fig))

app.layout =  dbc.Container([
    
         html.Div(children=output),
         html.Div(id='container',children=[]),
    
])

@app.callback(
    Output({'type':'container', 'index': MATCH}, 'children'),
    Input(component_id={'type': 'dynamic-graph', 'index': MATCH}, component_property='clickData')
    
)

def fig_click(clickData1):
  
    if not clickData1:
        raise dash.exceptions.PreventUpdate
    
    tab = dash.dash_table.DataTable(
        data=df.loc[df["city"].eq(clickData1["points"][0]["x"])]
        .to_dict("records"),
        columns=[{"name": i, "id": i} for i in df.columns],
    )
    
    
    return tab

if __name__ == '__main__':
    app.run_server(debug=True,use_reloader=False,)

@adamschroeder can you review and approve the code.

1 Like

@jhupiterz . The code is still in review for spam.
i appended all the plots and displayed in the layout. Later on i used advanced callback to display data when ever user click on a column of bar plot. The problem i am facing is that call back is not triggered at all.

hi @dashapp
I just wrote you a message since I am not able to access the data you sent here.

You can use any data to generate the required data frame. Can you explain the approach with any data?

hi @dashapp
let’s try to take a few steps back. I uploaded the data you tried to attach into a google drive so we can incorporate it into an example code.

Then, I did a small cleanup of your code so it would merely run.

import pandas as pd
import plotly.express as px
from dash import Dash, html, dcc, Output, Input, callback, dash_table, ALL, State, MATCH, ALLSMALLER
import dash_bootstrap_components as dbc


app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP],
                meta_tags=[{'name': 'viewport',
                            'content': 'width=device-width, initial-scale=1.0'}]
                )
df = pd.read_csv('nights.csv')
output =[]

for var in df.City.unique():  
  d1=df.loc[df.City==var]
  fig = px.bar(d1, x="City", y="Cost", barmode="group",
             )
  output.append(dcc.Graph(id={'type': 'dynamic-graph','index': var },figure=fig))

app.layout =  dbc.Container([
    
         html.Div(children=output),
         html.Div(id='container',children=[]),
    
])

@app.callback(
    Output({'type':'container', 'index': MATCH}, 'children'),
    Input(component_id={'type': 'dynamic-graph', 'index': MATCH}, component_property='clickData')
    
)

def fig_click(clickData1):
  
    if not clickData1:
        raise dash.exceptions.PreventUpdate
    
    tab = dash.dash_table.DataTable(
        data=df.loc[df["City"].eq(clickData1["points"][0]["x"])]
        .to_dict("records"),
        columns=[{"name": i, "id": i} for i in df.columns],
    )
    
    
    return tab

if __name__ == '__main__':
    app.run_server(debug=True,use_reloader=False,)

The resulting page is this:

Now, what would you like to do in this app?

Thank you @adamschroeder for taking your time to look into this. I want to display the dataframe when a user clicks on the bar plots. For example if a user clicks on the first plots, the required data should be displayed and when the user click on the other plot, that particular data should be updated. Is there a way to do this?

hi @dashapp

Are you looking for something like this?

import dash
import pandas as pd
import plotly.express as px
from dash import Dash, html, dcc, Output, Input, MATCH
import dash_bootstrap_components as dbc

df = pd.read_csv('assets/nights.csv')

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

output =[]
for var in df.City.unique():
    d1 = df.loc[df.City == var]
    fig = px.bar(d1, x="City", y="Cost", barmode="group")
    output.append(dcc.Graph(id={'type': 'dynamic-graph', 'index': var}, figure=fig))
    output.append( html.Div(id={'type': 'container', 'index':var}))


app.layout = dbc.Container([
    html.Div(output),
])


@app.callback(
    Output({'type': 'container', 'index': MATCH}, 'children'),
    Input(component_id={'type': 'dynamic-graph', 'index': MATCH}, component_property='clickData')

)
def fig_click(clickData1):
    if not clickData1:
        raise dash.exceptions.PreventUpdate


    tab = dash.dash_table.DataTable(
        data=df.loc[df["City"].eq(clickData1["points"][0]["x"])]
        .to_dict("records"),
        columns=[{"name": i, "id": i} for i in df.columns],
    )

    return tab


if __name__ == '__main__':
    app.run_server(debug=True, use_reloader=False, )
1 Like

@adamschroeder Thank you so much. this worked out.

1 Like