pythonpandasdataframe

Return Pandas dataframe row


I have a Pandas dataframe with checkbox widget. I would like to process the values from the row when the checkbox is checked.

Can anyone help me with this? My code is below.

        df = pagination.data_editor(data=pages[current_page - 1], use_container_width=True,
                        disabled=['Date','Day','Project','Task','StartTime','EndTime','Note','Total_Hours'],
                        column_order=['Date','Day','Project','Task','StartTime','EndTime','Total_Hours','Note','Delete','Edit'],
                        column_config=config,
                        key='edit_df')

            
            if not df.loc[df["Delete"]].empty:
                row = df.loc[df["Delete"] != df.loc[df["Delete"]].empty]
                entryid = row['id'].values
                
                

What I get here is a DataFrame object and not the value of the id column. What do I need to do to get just the value of id column?


Solution

  • Replace your if statement with the following:

    delete_rows = df.loc[df["Delete"]]
    if not delete_rows.empty:
        row = delete_rows.iloc[0]
        entryid = row["id"]
    

    Explanation

    Consider the following two-column dataframe:

    df = pd.DataFrame(
        {"Delete": [False, True, False, False],
        "id": [101, 102, 103, 104]}
    )
    

    Printed out, it looks like this

       Delete   id
    0   False  101
    1    True  102
    2   False  103
    3   False  104
    

    The number that you're after in this scenario is the 102 in the "id" column, where the Delete entry is True.

    df.loc[df["Delete"]] is the following "filtered" dataframe:

       Delete   id
    1    True  102
    

    It consists of all of the rows (of which there is only one) that have a True in the delete column.

    Things look promising: we've pulled out the row that we want. Keep in mind, however, that this is still a dataframe object. That is, it is "two-dimensional". To access an entry, we need to specify a column and a row (even though there's only one row in this dataframe).

    df.loc[df["Delete"]].empty is False in this case. It would be True if (and only if) there were no rows where the "Delete" entry is True. So, your if-condition successfully confirms that there is actually a row corresponding to a checked Delete-box.

    Your next line probably doesn't do what you think it does:

    df.loc[df["Delete"] != df.loc[df["Delete"]].empty]
    

    Because we're in if-block at this point, we know that df.loc[df["Delete"]].empty is False. So, everything that you have here is the same as

    df.loc[df["Delete"] != False]
    

    In other words, we're getting the rows where the Delete entry is True. But that's exactly what df.loc[df["Delete"]] was in the first place. Just as before, the result here is a dataframe rather than a series (i.e. it is still a two-dimensional array, not a one-dimensional array, which is what you seem to be after at this point).

    For a way to successfully get a series object for the only row of this dataframe, there are a few approaches you could take. What I opted for here was to use .iloc[0]. For a dataframe df, df.iloc[0] gives you the first row, as a series object. So, df.loc[df["Delete"]].loc[0] gives you the first (and only) row of the filtered dataframe, which is what we wanted.

    As an (arguably more principled) alternative, you could also use df.loc[df["Delete"]].squeeze(). .squeeze() will take a one-row or one-column dataframe and make it into a series (and will return the same dataframe if it has multiple rows and columns).

    One way or the other, the series row that you get looks like this when printed:

    Delete    True
    id         102
    Name: 1, dtype: object
    

    Once you properly get the row, all that remains is to extract the id-column entry, hence row["id"].