dash icon indicating copy to clipboard operation
dash copied to clipboard

[BUG] Documentation: Determining Which Cell Was Changed - Missing recipe in Editable DataTable chapter

Open iqdecay opened this issue 5 years ago • 4 comments

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 ?

iqdecay avatar Mar 24 '20 14:03 iqdecay

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

Thanks :)

daskr avatar Feb 10 '21 17:02 daskr

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

Sank-WoT avatar Sep 16 '21 11:09 Sank-WoT

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

OmaMansou avatar Feb 01 '22 10:02 OmaMansou

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.

jkondek1 avatar Sep 12 '22 06:09 jkondek1