Search code examples
pythonplotlydashboardplotly-dash

In a dashboard, graph a subset of the dataset depending on the value of a checkbox


I am using Dash to graph a dataset which contains columns for x, y, and another column for type of fruit. I have added in a checklist apples and grapes. What I want to do now is have the graph display the values of x and y for grapes if the grapes checkbox is ticked, apples if the apples checkbox is ticked, and both if both are ticked.

Would someone be able to help me? This is a really simple question I know.

I know I need to change the ‘def … return’ part somehow.

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go

app = dash.Dash()

fruits = {'Day':[1,2,3,4,5,6],
             'Visitors':[43,34,65,56,29,76],
             'Bounce_Rate':[65,67,78,65,45,52],
             'Nice_Fruits':['apple', 'apple', 'grape', 'apple', 'grape', 'grape']}
df_all_fruits = pd.DataFrame(fruits)

Nice_Fruits_list=df_all_fruits['Nice_Fruits'].unique()

app.layout = html.Div(children=[
html.H1('Payment Curve and predictor'),

 html.Label('fruits_1'),
    dcc.Checklist(
    id='fruits_checklist',
    options=[{'label': i, 'value': i} for i in Nice_Fruits_list],
        values=['apple', 'grape'],
    labelStyle={'display': 'inline-block'}
    ),

 dcc.Graph(
        id='fruits_graph',
        figure={
            'data': [
                go.Scatter(
                    x=df_all_fruits['Visitors'],
                    y=df_all_fruits['Bounce_Rate'],
                    mode='markers',
                    opacity=0.7,
                    marker={
                        'size': 15,
                        'line': {'width': 0.5, 'color': 'white'}
                    },
                )
            ],
            'layout': go.Layout(             
        xaxis={'type': 'linear', 'title': 'Visitors'},
                yaxis={'title': 'Bounce_Rate'},
                margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
                hovermode='closest'
            )
        }
    ),

])

@app.callback(
    Output('fruits_graph', 'figure'),
    [Input('fruits_checklist', 'values')]
)


   def update_graph(fruits_checklist_value):
    df = df_all_fruits[df_all_fruits.Nice_Fruits.isin([fruits_checklist_value])]

    return {
        'data': [go.Scatter(
            x= df['Visitors'],
            y= df['Bounce_Rate'],
        mode='markers',
            marker={
                'size': 15,
                'opacity': 0.5,
                'line': {'width': 0.5, 'color': 'white'}
            }
        )],
        'layout': {'margin': {'l': 40, 'r': 0, 't': 20, 'b': 30}}
    }

app.css.append_css({'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'})

if __name__ == '__main__':
    app.run_server()

Solution

  • So what you want is update your datas, and that's what you do, but to do so you'll have to put two plot on the same Scatter. You indeed want to modify the return. You need to iterate over the values in the Checkbox. And you then tell the graph to put the two scatters on the same graph:

    @app.callback(
    Output('fruits_graph', 'figure'),
    [Input('fruits_checklist', 'values')]
    )
    def update_graph(values):
          df = df_all_fruits
    
          return {'data': [go.Scatter(
            x= df[df['Nice_Fruits']==v]['Visitors'],
            y= df[df['Nice_Fruits']==v]['Bounce_Rate'],
        mode='markers',
            marker={
                'size': 15,
                'opacity': 0.5,
                'line': {'width': 0.5, 'color': 'white'}
            }
        ) for v in values],
        'layout': {'margin': {'l': 40, 'r': 0, 't': 20, 'b': 30}}
    }
    

    tell me if it solves your issue.