Interactive Graph
Add Index as Customdata
  • express
  • import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = pd.DataFrame({
        "x": [1,2,1,2, 1],
        "y": [1,2,3,4, 5],
        "label": ['s1', 's2', 's3', 's4', 's5'],
        "fruit": ["apple", "apple", "orange", "orange", "mango"]
    })
    
    fig = px.scatter(df, x="x", y="y", color="fruit", custom_data = ['label'])
    
    fig.update_traces(marker_size=20)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='hover-data')
        ])
    
    
    @app.callback(
        Output('hover-data', 'children'),
        Input('basic-interactions', 'hoverData'))
    def display_hover_data(hoverData):
        return json.dumps(hoverData, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
  • graph object
  • import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.graph_objects as go
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = pd.DataFrame({
        "x": [1,2,1,2, 1],
        "y": [1,2,3,4, 5],
        "label": ['s1', 's2', 's3', 's4', 's5'],
        "fruit": ["apple", "apple", "orange", "orange", "mango"]
    })
    
    fig = go.Figure()
    
    temp = df[df['fruit'] == 'apple']
    trace = go.Scatter(x = temp['x'], y = temp['y'], mode='markers', customdata = temp.index)
    fig.add_trace(trace)
    
    temp = df[df['fruit'] == 'orange']
    trace = go.Scatter(x = temp['x'], y = temp['y'], mode='markers', customdata = temp.index)
    fig.add_trace(trace)
    
    temp = df[df['fruit'] == 'mango']
    trace = go.Scatter(x = temp['x'], y = temp['y'], mode='markers', customdata = temp.index)
    fig.add_trace(trace)
    
    fig.update_traces(marker_size=20)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='hover-data')
        ])
    
    
    @app.callback(
        Output('hover-data', 'children'),
        Input('basic-interactions', 'hoverData'))
    def display_hover_data(hoverData):
        return json.dumps(hoverData, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Mode
  • clickmode, determines the mode of single click interactions
  • import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = pd.DataFrame({
        "x": [1,2,1,2, 1],
        "y": [1,2,3,4, 5],
        "label": ['s1', 's2', 's3', 's4', 's5'],
        "fruit": ["apple", "apple", "orange", "orange", "mango"]
    })
    
    fig = px.scatter(df, x="x", y="y", color="fruit", custom_data = ['label'])
    
    fig.update_layout(clickmode='event+select')
    
    fig.update_traces(marker_size=20)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_click_data(clickData):
        return json.dumps(clickData, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
  • dragmode, determines the mode of drag interactions
  • import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = pd.DataFrame({
        "x": [1,2,1,2, 1],
        "y": [1,2,3,4, 5],
        "label": ['s1', 's2', 's3', 's4', 's5'],
        "fruit": ["apple", "apple", "orange", "orange", "mango"]
    })
    
    fig = px.scatter(df, x="x", y="y", color="fruit", custom_data = ['label'])
    
    fig.update_layout(dragmode = "select")
    
    fig.update_traces(marker_size=20)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'selectedData'))
    def display_selected_data(selectedData):
        return json.dumps(selectedData, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
  • hovermode, determines the mode of hover interactions
  • Interactive Information
  • hoverData, data when mouse is hovered
  • clickData, data selected by clicking
  • selectedData, data selected with box select or lasso select
  • relayoutData, click and drag on the graph to zoom or click on the zoom buttons in the graph's menu bar, or click on legend items
  • import json
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output, State
    from dash.exceptions import PreventUpdate
    import plotly.graph_objects as go
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv')
    temp = df[df['Country Name'] == 'Canada']
    df = temp[temp['Indicator Name'] == 'CO2 emissions (metric tons per capita)']
    
    def get_fig(data):
        fig = go.Figure(go.Scatter(x=data['Year'], y=data['Value']))
        return fig
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=get_fig(df)
        ),
    
        html.Pre(id='output'),
        html.Pre(id='output2'),
        ])
    
    @app.callback(
        Output('output2', 'children'),
        Input('basic-interactions', 'hoverData'),
        Input('basic-interactions', 'clickData'),
        Input('basic-interactions', 'selectedData'))
    def display_selected_data(hoverData, clickData, selectedData):
        return str(hoverData)+'\n'+str(clickData)+'\n'+str(selectedData)
    
    @app.callback(
        Output('output', 'children'),
        Output('basic-interactions', 'figure'),
        Input('basic-interactions', 'relayoutData'),
        State('basic-interactions', 'figure'))
    def display_relayout_data(relayoutData, fig):
        if not relayoutData:
            raise PreventUpdate
        if 'autosize' in relayoutData.keys():
            print('autosize')
        if 'xaxis.autorange' in relayoutData.keys():
            return json.dumps(relayoutData, indent=2), get_fig(df)
            print('reset')
        if 'xaxis.range[0]' in relayoutData.keys():
            xl = relayoutData['xaxis.range[0]']
            xr = relayoutData['xaxis.range[1]']
            yl = relayoutData['yaxis.range[0]']
            yr = relayoutData['yaxis.range[1]']
            df_selected = df.loc[(df.Year > xl) & (df.Year < xr) & (df.Value > yl) & (df.Value < yr)]
            return json.dumps(relayoutData, indent=2), get_fig(df_selected)
    
        return json.dumps(relayoutData, indent=2), get_fig(df)
    
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Scatter
    # Plotly Express
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = pd.DataFrame({
        "x": [1,2,1,2, 1],
        "y": [1,2,3,4, 5],
        "label": ['s1', 's2', 's3', 's4', 's5'],
        "fruit": ["apple", "apple", "orange", "orange", "mango"]
    })
    
    fig = px.scatter(df, x="x", y="y", color="fruit", custom_data = ['label'])
    
    fig.update_traces(marker_size=20)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'relayoutData'))
    def display_relayout_data(relayoutData):
        return json.dumps(relayoutData, indent=2)
    
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    # Graph Objective
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.graph_objects as go
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = pd.DataFrame({
        "x": [1,2,1,2, 1],
        "y": [1,2,3,4, 5],
        "label": ['s1', 's2', 's3', 's4', 's5'],
        "fruit": ["apple", "apple", "orange", "orange", "mango"]
    })
    
    df.index = ['r1', 'r2', 'r3', 'r4', 'r5']
    
    fig = go.Figure()
    
    trace = go.Scatter(x = df['x'], y = df['y'], mode='markers', customdata = df.index)
    fig.add_trace(trace)
    
    fig.update_layout(clickmode='event+select', dragmode = "lasso")
    
    fig.update_traces(marker_size=20)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'selectedData'))
    def display_selected_data(selectedData):
        if selectedData:
            indices = [p['customdata'] for p in selectedData['points']]
            temp = df.loc[indices]
            return temp.to_string()
        return json.dumps(selectedData, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
    		
    Pie
    # Plotly Express
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder().query("year == 2007").query("continent == 'Europe'")
    df.loc[df['pop'] < 2.e6, 'country'] = 'Other countries'
    
    fig = px.pie(df, values='pop', names='country', custom_data = ['country'], title='Population of European continent')
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            country = data['points'][0]['label']
            return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    # Graph Objective
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import plotly.graph_objects as go
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder().query("year == 2007").query("continent == 'Europe'")
    df.loc[df['pop'] < 2.e6, 'country'] = 'Other countries'
    
    fig = go.Figure()
    
    trace = go.Pie(values = df['pop'], labels = df['country'])
    fig.add_trace(trace)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        #if data:
            #country = data['points'][0]['label']
            #return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Histogram
    # Plotly Express
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder().query("year == 2007").query("continent == 'Europe'")
    df.loc[df['pop'] < 2.e6, 'country'] = 'Other countries'
    
    df = px.data.tips()
    fig = px.histogram(df, x="total_bill", nbins=40)
    
    fig.update_layout(bargap=0.1)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    # Graph Objective
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import plotly.graph_objects as go
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder().query("year == 2007").query("continent == 'Europe'")
    df.loc[df['pop'] < 2.e6, 'country'] = 'Other countries'
    
    df = px.data.tips()
    
    fig = go.Figure()
    trace = go.Histogram(x = df["total_bill"])
    fig.add_trace(trace)
    
    fig.update_layout(bargap=0.1)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            return df.iloc[data['points'][0]['pointNumbers']].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Bar
    # Plotly Express
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder().query("year == 2007").query("continent == 'Europe'")
    df.loc[df['pop'] < 2.e6, 'country'] = 'Other countries'
    
    fig = px.bar(df, x='country', y='pop')
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            country = data['points'][0]['label']
            return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    # Graph Objective
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.graph_objects as go
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder().query("year == 2007").query("continent == 'Europe'")
    df.loc[df['pop'] < 2.e6, 'country'] = 'Other countries'
    
    fig = go.Figure()
    trace = go.Bar(x = df['country'], y = df['pop'])
    fig.add_trace(trace)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            #return df.iloc[data['points'][0]['pointNumbers']].to_string()
            country = data['points'][0]['label']
            return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Line
    # Plotly Express
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder().query("continent=='Americas'")
    fig = px.line(df, x="year", y="lifeExp", color='country', markers=True, custom_data=['country', 'year'])
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            country = data['points'][0]['customdata'][0]
            year = data['points'][0]['customdata'][1]
            return df.loc[(df['country'] == country) & (df['year'] == year)].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Box
    # Plotly Express
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder()
    fig = px.box(df, x = 'country', y="lifeExp")
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            country = data['points'][0]['x']
            return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    # Graph Objective
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.graph_objects as go
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder()
    
    fig = go.Figure()
    trace = go.Box(x = df['country'], y = df['lifeExp'])
    fig.add_trace(trace)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            country = data['points'][0]['x']
            return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Violin
    # Plotly Express
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder()
    fig = px.violin(df, x = ['country'], y="lifeExp")
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            country = data['points'][0]['x']
            return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    # Graph Objective
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import plotly.graph_objects as go
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder()
    
    fig = go.Figure()
    trace = go.Violin(x = df['country'], y = df['lifeExp'])
    fig.add_trace(trace)
    
    app.layout = html.Div([
        dcc.Graph(
            id='basic-interactions',
            figure=fig
        ),
    
        html.Pre(id='output')
        ])
    
    @app.callback(
        Output('output', 'children'),
        Input('basic-interactions', 'clickData'))
    def display_selected_data(data):
        if data:
            country = data['points'][0]['x']
            return df[df['country'] == country].to_string()
        return json.dumps(data, indent=2)
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Cross Interaction between Graphs
    import json
    
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    from dash.exceptions import PreventUpdate
    import plotly.graph_objects as go
    import plotly.express as px
    import pandas as pd
    
    app = dash.Dash(__name__)
    
    df = px.data.gapminder()
    
    sub_operation = False
    
    app.layout = html.Div([
        dcc.Graph(
            id='g1',
        ),
    
        dcc.Graph(
            id='g2',
        ),
    
        html.Pre(id='output1'),
        ])
    
    def get_g1_plot(data):
        fig = go.Figure()
    
        trace = go.Scatter(x = data['lifeExp'], y = data['gdpPercap'], mode='markers')
        fig.add_trace(trace)
    
        return fig
    
    def get_g2_plot(data):
        fig = go.Figure()
    
        trace = go.Pie(values = data['pop'], labels = data['continent'])
        fig.add_trace(trace)
    
        return fig
    
    def data_screened(data, data_g1, data_g2, sub):
        temp = data
    
        if data_g1 and 'xaxis.range[0]' in data_g1:
            xl = data_g1['xaxis.range[0]']
            xr = data_g1['xaxis.range[1]']
            yl = data_g1['yaxis.range[0]']
            yr = data_g1['yaxis.range[1]']
            temp = temp.loc[(temp.lifeExp > xl) & (temp.lifeExp < xr) & (temp.gdpPercap > yl) & (temp.gdpPercap < yr)]
    
        if data_g2 and sub:
            country = data_g2['points'][0]['label']
            temp = temp[temp['continent'] == country]
    
        return temp
    
    @app.callback(
        Output('g1', 'figure'),
        Output('g2', 'figure'),
        Output('output1', 'children'),
        Input('g1', 'relayoutData'),
        Input('g2', 'clickData')
        )
    def display_selected_data(data_g1, data_g2):
        ctx = dash.callback_context
        global sub_operation
    
        if data_g1:
            # auto selection
            if 'xaxis.range[0]' not in data_g1:
                # operations by clicking reset button
                if 'xaxis.autorange' in data_g1:
                    # reset operation
                    if sub_operation:
                        sub_operation = False
                        return get_g1_plot(df), get_g2_plot(df), str(df.shape)
                    # click operation on pie chart
                    else:
                        sub_operation = True
                        temp = data_screened(df, data_g1, data_g2, sub_operation)
                        return get_g1_plot(temp), get_g2_plot(temp), temp.to_string()
                # click operation following auto selection
                if data_g2:
                    sub_operation = True
                    temp = data_screened(df, data_g1, data_g2, sub_operation)
                    return get_g1_plot(temp), get_g2_plot(temp), temp.to_string()
                # intial auto selection
                sub_operation = False
                return get_g1_plot(df), get_g2_plot(df), str(df.shape)
    
            # select operation on scatter plot
            if ctx.triggered[0]['prop_id'].split('.')[0] == 'g1':
                temp = data_screened(df, data_g1, data_g2, sub_operation)
                return get_g1_plot(temp), get_g2_plot(temp), temp.to_string()
    
            # click operation on pie chart
            if ctx.triggered[0]['prop_id'].split('.')[0] == 'g2':
                sub_operation = True
                temp = data_screened(df, data_g1, data_g2, sub_operation)
                return get_g1_plot(temp), get_g2_plot(temp), temp.to_string()
    
        # initial state
        return go.Figure(), go.Figure(), 'Plotting ...'
    
    if __name__ == '__main__':
        app.run_server(debug=True)
            
    Reference
  • Mode
  • Graph Objects
  • Express
  • Python Figure Reference
  • Tutorial