Search code examples
pythonplotlyplotly-dash

Is it possible to filter the dash datatable with the first row always unfiltered


I need to plot a 3D scatter and data table in Dash.

My intention is to be able to use the data table to filter the scatter plot. The first row of my data is the target. Is it possible for the filter to always keep the first row?

For example, I tried using the solar.csv to build a mockup:

from dash import Dash, dash_table
import pandas as pd
from dash.dependencies import Input, Output
import plotly.express as px
from dash import Dash, dash_table, html, dcc

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')

app = Dash(__name__)

app.layout = dash_table.DataTable(
    df.to_dict('records'), 
    [{"name": i, "id": i} for i in df.columns],
    filter_action='native'
)

app.layout = html.Div([
    dash_table.DataTable(
        id='datatable-interactivity',
        data = df.to_dict('records'), 
        columns = [{"name": i, "id": i} for i in df.columns],
        filter_action='native'
    ),
    html.Div(id='scatter-container')

])

@app.callback(
    Output(component_id='scatter-container', component_property='children'),
    Input(component_id='datatable-interactivity', component_property="derived_virtual_data")
)
def update_scatter(all_rows_data):
    dff = pd.DataFrame(all_rows_data)
    fig = px.scatter(dff, x='Number of Solar Plants', y = 'Generation (GWh)')
    return dcc.Graph(figure=fig)

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

Assume the first row (California) is my target, is it possible to show both California and Arizona when I type "Arizona" in the filter field and hence show both California and Arizona in the scatter plot?


Solution

  • There may be many approaches, but one way to always display fixed rows is to create an additional graph on the graph created by the filtered data frame. go's graph object is used to add markers. And, I matched the hover data to the original graph.

    def update_scatter(all_rows_data):
        dff = df if all_rows_data is None else pd.DataFrame(all_rows_data)
        fig = px.scatter(dff, x='Number of Solar Plants', y='Generation (GWh)')
        fig.add_trace(go.Scatter(x=[df.loc[0, 'Number of Solar Plants']],
                                 y=[df.loc[0,'Generation (GWh)']],
                                 mode='markers',
                                 marker=dict(color='#636efa'),
                                 showlegend=False,
                                 hovertemplate='Number of Solar Plants=%{x}<br>Generation (GWh)%{y}'
                                ))
        return dcc.Graph(figure=fig)
    

    enter image description here