Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a datatable updated by 2 dropdowns as inputs in Plotly Python

As titled, i am creating a plotly dashboard with a data-table only. There will be 2 drop-downs as inputs, and the data-table will update according to the drown-downs. How do I set the layout and callbacks?

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

df = pd.read_csv(data, header=0, encoding = 'utf8')

app = dash.Dash()
application = app.server

dropdown = html.Div([html.Label('district'),
             dcc.Dropdown(id='dropdown_d',
                          options=[{'label': i, 'value': i} for i in df["district"].unique()], value='none'),
             html.Label('address'),
             dcc.Dropdown(id='dropdown_a',
                          options=[{'label': i, 'value': i} for i in df["address"].unique()], value='none')])

final_table = html.Div([dash_table.DataTable(id="final_table")])

app.layout = html.Div([dropdown, final_table])

@app.callback(Output('final_table', 'data'),
          [Input('dropdown_d', 'value'),
           ])

def update_table(selected_value):
    df = pd.read_csv(data, header=0, encoding = 'utf8')
    df_updated = df[df["district"] == selected_value]
    columns = [{'name': i, 'id': i} for i in df_updated.columns]
    data = df.to_dict('records')
    return columns, data

if __name__ == "__main__":
    app.run_server(debug=True, port=8055)

This is the farthest i can get. The code above is only trying to update the data-table from 1 dropdown value, but my goal is to update by 2 dropdown values.

any help is very much appreciated. in case the data file is needed, here is the link to the data.

like image 797
yts61 Avatar asked Oct 24 '25 15:10

yts61


1 Answers

Here is the snippet of the working code, I have added comments for clarification,

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

df = pd.read_csv("https://elartedm.com/wp-content/uploads/2020/03/data_hk.csv", header=0, encoding = 'utf8')

app = dash.Dash()
application = app.server

dropdown = html.Div([
    html.Label('district'),
    dcc.Dropdown(id='dropdown_d1', options=[{'label': i, 'value': i} for i in df["District"].unique()], value=None),
    html.Label('address'),
    dcc.Dropdown(id='dropdown_d2', options=[], value=None)
])


#its better to have a Div here so that you can update the entire div in the callback and add the necessary properties in the callback
final_table = html.Div(id="final_table")

app.layout = html.Div([dropdown, final_table])


#callback to update second dropdown based on first dropdown
#This callback is used to update the second dropdown based on the value selected in the first dropdown so that its dynamically updated (this is a good  practice rather than having a static list of options).
@app.callback(Output('dropdown_d2', 'options'),
          [
            Input('dropdown_d1', 'value'),
          ])
def update_dropdown_2(d1):
    print(d1)
    if(d1 != None):
        df_filtered = df[(df["District"]==d1)]
        return [{'label': i, 'value': i} for i in df_filtered["Address"].unique()]
    else:
        return []


#this callback to update the final table should be based on both the input dropdown values, so the input parameters are two dropdown_d1, dropdown_d2
#based on these values filter the dataframe and update the table
#since dataframe is a global declaration you don't need to again consume it here.
@app.callback(Output('final_table', 'children'),
          [
            Input('dropdown_d1', 'value'),
            Input('dropdown_d2', 'value'),
          ])
def update_table(d1, d2):

    if(d1 != None and d2 != None):
        df_filtered = df[(df["District"]==d1) & (df["Address"]==d2)]

        return [dt.DataTable(
            id='table',
            columns=[{"name": i, "id": i} for i in df_filtered.columns],
            data=df_filtered.to_dict('records'),
        )]
    else:
        print("none")
        return []


if __name__ == "__main__":
    app.run_server(debug=True, port=8055)

Hope it helps.

like image 188
n00b Avatar answered Oct 26 '25 04:10

n00b



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!