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?
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"]
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"]
.