3

I'm hoping for some guidance on creating a dashboard using Dash by Plotly in Python. Although there is a lot of documentation and forums posts available online, I feel that they assume some knowledge that I may be missing, particularly in correctly using callbacks to implement interactivity.

What I am trying to achieve is a dashboard that will allow me to:

  1. Upload an Excel file
  2. Select a column from the Excel file
  3. Run a function to process data from that column
  4. Display resulting output data in a table

I have tried to create a minimal working example but have struggled. Here's what I've managed so far:

import base64
import io
import pandas as pd
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

## 1. Define overall dashboard layout

Dashboard = dash.Dash(__name__, external_stylesheets=['https://codepen.io/chriddyp/pen/bWLwgP.css'])
Dashboard.layout = html.Div([
                             html.H1('Dashboard Prototype', style={'width':'100%', 'textAlign': 'center'}),
                             dcc.Upload(
                                       id       = 'Dashboard_Input',
                                       children = html.A('Select Files'),
                                       style    = {'width': '100%', 'height': '60px', 'lineHeight': '60px', 'borderWidth': '1px',
                                                   'borderStyle': 'dashed', 'borderRadius': '5px', 'textAlign': 'center', 'display': 'inline-block'},
                                       multiple = True
                                       ),
                             html.Br(),
                             html.Div(id='Dashboard_Dropdown'),
                             html.Br(),
                             html.Div(id='Dashboard_Output')
                           ])

## 2. Define functions to upload, process and present data

def selectData(contents, filename, date):

    content_type, content_string = contents.split(',')
    decoded = base64.b64decode(content_string)

    try:
        Raw_Data = pd.read_excel(io.BytesIO(decoded))
    except Exception as e:
        return html.Div(['There was an error processing this file.'])

    Dropdown = html.Div([                      
                         html.H4 (('File Name: ', filename), style={'width':'100%', 'textAlign': 'center'}),
                         html.Br(),
                         dcc.Dropdown(
                                      id          = 'Dataset_and_Column',
                                      options     = [{'label': i, 'value': i} for i in Raw_Data.columns],
                                      style       = {'width': '100%', 'height': '60px', 'lineHeight': '60px', 'borderWidth': '1px',
                                                     'borderStyle': 'dashed', 'borderRadius': '5px', 'textAlign': 'center', 'display': 'inline-block'},
                                      placeholder =  'Select Dataset Column'
                                     ),
                         html.Br(),
                        ])

    return Dropdown

def processData(Raw_Data, Column_Label):

    # DO SOME PROCESSING THAT RESULTS IN 'TABLE':
    Table      = Table
    HTML_Table = html.Div([ 
                           dash_table.DataTable(
                                                data         = Table.to_dict('records'),
                                                columns      = [{'name': i, 'id': i} for i in Table.columns],
                                                style_cell   = {'textAlign': 'center', 'width': '100px'}, 
                                                editable     = False,
                                                style_header = {'fontWeight': 'bold', 'textAlign': 'center'},
                                                style_table  = {'maxHeight': '50ex', 'width': '100%'}
                                               ),
                           html.Hr()
                         ])
    return HTML_Table

## 4. Define callback functions

Dashboard.config.suppress_callback_exceptions = True

@Dashboard.callback(
                    Output('Dashboard_Dropdown', 'children'),
                    [Input('Dashboard_Input'   , 'contents')],
                    [State('Dashboard_Input'   , 'filename'), State('Dashboard_Input', 'last_modified')]
                   )
def createDropdown(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
       Dropdown = [selectData(c, n, d) for c, n, d in zip(list_of_contents, list_of_names, list_of_dates)]
       return Dropdown

################################################################################
################################################################################

# THIS BIT DOESN'T WORK #
# Need to make this callback function take an input of Raw_Date and Column_Label (selected from the dropdown) to run the processData() function.

@Dashboard.callback(
                    Output('Dashboard_Output'  , 'children'),
                    [Input('Dataset_and_Column', 'contents'), Input('Dataset_and_Column', 'value')],
                   )
def processSelectedColumn(contents, value):

    # HTML_Table = processData(contents, value)

    return value#HTML_Table

    # ^^^^^^ Note that this allow 'value' to be printed on the dashboard but 
    # when the commented 'HTML_Table' bits are uncommented it fails

################################################################################
################################################################################

## 6. Run dashboard

if __name__ == '__main__':
    Dashboard.run_server(debug=True)

This allows me to select an Excel file and then print the selected column of the Pandas data frame created from it but I am unsure exactly how to connect it all together to run my processData() function on the selected column.

Any ideas on how I've not correctly used or connected up the callbacks, functions, etc.?

Pyy
  • 327
  • 6
  • 23

2 Answers2

1

You'll need the processSelectedColumn callback to accept a value from the dropdown as an Input as well. It might also be possible/good to take the data from the upload as State instead of Input. That should give you the values you need to perform your desired calculation.

coralvanda
  • 6,431
  • 2
  • 15
  • 25
1

Answer:

Below are some code snippets to select a given columns from dropdown in Dash.

  1. Data set Housing price:

    df= pd.read_csv(r"housing_price.csv")

  2. Save columns in a variable say options to call in html tag of dash.

    options = [] for col in df.columns: options.append({'label':'{}'.format(col, col), 'value':col})

  3. Write a html tag for deafault drop-down:

`

app.layout = html.Div([
        html.Label("Select a feature from drop-down to plot HISTOGRAM"),
        dcc.Dropdown(
            id = 'my_dropdown1',
            options= options,
            value='Choose columns'
        ),
        html.Label(id='my_label1'),

        html.Button(
            id='submit-button',
            n_clicks=0,
            children='Submit',
            style={'fontSize':24, 'marginLeft':'30px'}
        )
        ])
  1. Write the call-back:

    @app.callback( Output('my_label1', 'children'), [Input('my_dropdown1', 'value')] ) def update_dropdown(value): return 'You have chosen {} for histogram plot!'.format(value)

NOTE: If you want to use State follow along below code to activate call to selected column after user clicks submit button.

  1. Activate State based callback:

    @app.callback(
        Output('my_label1', 'children'),
        [Input('submit-button', 'n_clicks')],
        [State('my_dropdown1','value')]
        )
    
    def update_dropdown_state(n_clicks,value):
        return 'You have chosen {} for histogram plot!'.format(value)
    
DataFramed
  • 1,491
  • 16
  • 21