Robert Marciniak
Robert Marciniak

Reputation: 303

Dash plotly Datatable column filtering or cropping

I have implemented a live-update datatable to correspond with a live-update graph. Functionally, both work very well. I do have a problem with filtering the datatable to include certain columns and exclude others. For ex. If the graph is zoomed in for certain x-value (09:00-10:00), is there any way I can also crop the corresponding datatable to represent columns from that same value? Perhaps add a button with a callback that deletes specific column ids? Is there a way to delete specific 'column' 'id' inputs through python with out using the GUI? As of now, I can only manually delete individual columns which is very tedious given the amount of columns. Thank you. I hope this question is not too open-ended.

enter image description here

table_contents = ['Propofol/Remi @ 6.5 ug/ml', 'Fentanyl (ug)', 'Propofol (mg)', 'Remi (ug)',
                  'Ketorolac (mg)']
html.Div([dash_table.DataTable(
        id='editing-columns',
        columns=[{
            'name': 'Parameter',
            'id': 'column1',
            'deletable': True,
            'renamable': True
        }],
        data=[
            {'column1': j}
            for j in table_contents
        ],
        editable=True,
    )]),

# The callback stores the previous length of the csv file in dcc.store and appends new columns if new csv data uploaded
@app.callback(Output('editing-columns', 'columns'),
             [Input('graph-update', 'n_intervals')],
              [State('editing-columns', 'columns')],
              [State('mystore', 'data')])
def update_columns(n, btn, existing_columns, data):
   
            with open('temp.csv', 'r') as rf:
                reader = csv.reader(rf)
                for a in reader:
                    existing_columns.append({
                        'id': a[3], 'name': a[3],
                        'renamable': True, 'deletable': True
                })

            return existing_columns, html.Div('Program running')

        else:
            check_length = []
            de_serialized = json.loads(data)
            with open('temp.csv', 'r') as rf:
                reader = csv.reader(rf)
                for a in reader:
                    check_length.append(a[3])

            if len(check_length) == 0:
                return existing_columns, html.Div('Program running')

            elif len(check_length) > len(de_serialized):
                existing_columns.append({
                    'id': check_length[-1], 'name': check_length[-1],
                    'renamable': True, 'deletable': True
                })
                return existing_columns, html.Div('Program running')

            else:
                return existing_columns, html.Div('Program running')
#The graph is a bar and scatter graph that is updated with x,y values derived from the same csv as the datatable.
@app.callback(
    dash.dependencies.Output('live-graph', 'figure'),
    [dash.dependencies.Input('graph-update-BP', 'n_intervals')],
)
def update_graph_scatter_1(btn, n):
        trace = []
        trace2 = []

        blood_pressure = []
        hr = []
 with open('temp.csv', 'r') as rf:
            reader_2 = csv.reader(rf)
            for a in reader_2:
                blood_pressure.append(eval(a[4]))
                time.append(a[3])
        for i in range(0, len(blood_pressure)):
            trace.append(go.Box(y=blood_pressure[i],
                                x=triple_time[i],
                                line=dict(color='#6a92ff'),
                                hoverinfo='all'))
        for a in range(0, len(hr)):
            trace2.append(go.Scatter(y=coated_hr[a],
                                     x=coated_time[a],
                                     name='HR',

Upvotes: 1

Views: 1170

Answers (1)

Igna
Igna

Reputation: 1127

Whenever you pan or zoom, a relayoutData interaction is triggered, from there you can get the axis ranges.

The dcc.Graph component has four attributes that can change through user-interaction: hoverData, clickData, selectedData, relayoutData. These properties update when you hover over points, click on points, or select regions of points in a graph. https://dash.plotly.com/interactive-graphing

import json

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
import plotly.express as px
import pandas as pd

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

df = pd.DataFrame({
    "x": [1,2,1,2],
    "y": [1,2,3,4],
    "customdata": [1,2,3,4],
    "fruit": ["apple", "apple", "orange", "orange"]
})

fig = px.scatter(df, x="x", y="y", color="fruit", custom_data=["customdata"])
fig.update_traces(marker_size=20)


app.layout = html.Div([
    dcc.Graph(
        id='basic-interactions',
        figure=fig
    ),

    html.Div(className='row', children=[

        html.Div([
            dcc.Markdown("""
                **Zoom and Relayout Data**

                Click and drag on the graph to zoom or click on the zoom
                buttons in the graph's menu bar.
                Clicking on legend items will also fire
                this event.
            """),
            html.Pre(id='relayout-data'),
        ])
    ])
])



@app.callback(
    Output('relayout-data', 'children'),
    Input('basic-interactions', 'relayoutData'))
def display_relayout_data(relayoutData):
    if relayoutData is None:
        raise PreventUpdate
    elif "xaxis.range[0]" not in relayoutData.keys():
        raise PreventUpdate
    else:
    #get the relevant axis ranges, you can use to drop columns from the datatable
        print(relayoutData,type(relayoutData))
        return json.dumps(relayoutData, indent=2)


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

Upvotes: 1

Related Questions