plotly / dash

Data Apps & Dashboards for Python. No JavaScript Required.
https://plotly.com/dash
MIT License
21.35k stars 2.06k forks source link

Determining Which Cell Was Changed - Missing recipe in Editable DataTable chapter #1162

Open iqdecay opened 4 years ago

iqdecay commented 4 years ago

On the chapter about Editable DataTable we can find this :

This chapter includes recipes for:
    Reading the contents of the DataTable
    Filtering out null values
    Uploading data
    Determining which cell has changed 
    Adding or removing columns
    Adding or removing rows
    Clearable, deletable, renamable, and hideable columns
    Export DataTable

However, no recipe is provided for Determining which cell has changed. Is this because there is no "API-way" to do it ?

daskr commented 3 years ago

Any updates on this? I would also be interested in the recipe for "Determining which cell has changed".

Thanks :)

Sank-WoT commented 3 years ago

ehhh A year has passed, and so they did not introduce this functionality

OmaMansou commented 2 years ago

I managed to find a fix, albeit not very elegant, but it works in my use case. I do not find the exact cell that has changed, but only the line.

Suppose that your DataTable is called table.

def get_modified_line(timestamp, table, table_previous):
    # Here, table comes from State('table', 'data') and table_previous from State('table', 'data_previous'). 
    # To trigger the callback, use Input('table', 'data_timestamp').

    table = pd.DataFrame(table)
    previous_table = pd.DataFrame(table_previous)

    editable_columns = [] # This list should contain the columns that are editable (those that can change with user input, plus a line identifier such as the index)

    # We concatenate the two table and rop the duplicates in order to keep the previous state and the actual state of the line that has changed
    modified = pd.concat([table , previous_table ]).drop_duplicates(keep=False)

    # We keep the last line of the two remaining lines (last line because of the order in concat)
    modified = modified.drop_duplicates(keep='last', subset=editable_columns)

    # We grab the only line (just to be safe), assuming that only one line can change at a time, using .iloc[[0]] 
    modified = modified.reset_index(drop=True).iloc[[0]]

    return modified
jkondek1 commented 2 years ago

I managed to find a fix, albeit not very elegant, but it works in my use case. I do not find the exact cell that has changed, but only the line.

Suppose that your DataTable is called table.

def get_modified_line(timestamp, table, table_previous):
    # Here, table comes from State('table', 'data') and table_previous from State('table', 'data_previous'). 
    # To trigger the callback, use Input('table', 'data_timestamp').

    table = pd.DataFrame(table)
    previous_table = pd.DataFrame(table_previous)

    editable_columns = [] # This list should contain the columns that are editable (those that can change with user input, plus a line identifier such as the index)

    # We concatenate the two table and rop the duplicates in order to keep the previous state and the actual state of the line that has changed
    modified = pd.concat([table , previous_table ]).drop_duplicates(keep=False)

    # We keep the last line of the two remaining lines (last line because of the order in concat)
    modified = modified.drop_duplicates(keep='last', subset=editable_columns)

    # We grab the only line (just to be safe), assuming that only one line can change at a time, using .iloc[[0]] 
    modified = modified.reset_index(drop=True).iloc[[0]]

    return modified

Hi, unfortunately this does not work generally. In particular if the original dataframe has already duplicates, the duplicate dropping won't work as intended.