Thansk @sis , Yeah it was helpful and managed to fix the issue with row selected. But I just want to delete these selected rows and display the updated table. Any thoughts on how to do that?
@rchamila a possible solution to your case is given by the below snippet (consider that I am no expert in neither AG Grid nor streamlit-aggrid components, so maybe some implementations can be improved)
It works for both single and multiple rows selection.
Snippet
import string
import numpy as np
import pandas as pd
import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder, GridUpdateMode
st.set_page_config(layout='wide')
def display_table(df: pd.DataFrame, selection: str) -> AgGrid:
# Configure AgGrid options
gb = GridOptionsBuilder.from_dataframe(df)
gb.configure_selection(selection)
st.write(f"Dataframe shape: {df.shape}")
return AgGrid(
df,
gridOptions=gb.build(),
# this override the default VALUE_CHANGED
update_mode=GridUpdateMode.MODEL_CHANGED
)
# Define dummy data
rng = np.random.default_rng(2021)
N_SAMPLES = 100
N_FEATURES = 10
df = pd.DataFrame(rng.integers(0, N_SAMPLES, size=(
N_SAMPLES, N_FEATURES)), columns=list(string.ascii_uppercase[:N_FEATURES]))
cols = st.beta_columns(2)
with cols[0]:
st.markdown('# 🠔 Before')
# Display AgGrid from data and write response
st.markdown("### 1️⃣ Let's display dummy data through AgGrid")
selection = st.radio('Selection mode', ['single', 'multiple'])
response = display_table(df, selection=selection)
st.markdown(
"### 2️⃣ AgGrid response contains `data` (original df) and `selected_rows`")
for k, v in response.items():
st.write(k, v)
with cols[1]:
st.markdown('# 🠖 After')
# Retrieve selected rows indices
st.markdown(
"### 3️⃣ From selected rows we can obtain dataframe indices to drop")
data = response['data'].to_dict(orient='records')
indices = [data.index(row) for row in response['selected_rows']]
st.write(f"Selected rows are located at indices: {indices}")
# Use retrieved indices to remove corresponding rows from dataframe
st.markdown(
"### 4️⃣ Display the updated dataframe where rows have been removed")
_df = df.drop(indices, axis=0)
st.write(f"Dataframe shape: {_df.shape}")
AgGrid(_df)
@rchamila following this example in streamlit-aggrid repo and this blog post, I found a way to achieve what you need (interactive row deletion) through custom JavaScript injection
Solution
import string
import numpy as np
import pandas as pd
import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder, GridUpdateMode, JsCode
st.set_page_config(layout='wide')
def display_table(df: pd.DataFrame) -> AgGrid:
# Configure AgGrid options
gb = GridOptionsBuilder.from_dataframe(df)
gb.configure_selection('single', use_checkbox=True)
# Custom JS code for interactive rows deletion
# For credits SEE:
# https://github.com/PablocFonseca/streamlit-aggrid/blob/1acb526ba43b5aac9c8eb22cc54eeb05696cd84d/examples/example_highlight_change.py#L21
# https://ag-grid.zendesk.com/hc/en-us/articles/360020160932-Removing-selected-rows-or-cells-when-Backspace-or-Delete-is-pressed
js = JsCode("""
function(e) {
let api = e.api;
let sel = api.getSelectedRows();
api.applyTransaction({remove: sel});
};
""")
gb.configure_grid_options(onRowSelected=js)
return AgGrid(
df,
gridOptions=gb.build(),
# this override the default VALUE_CHANGED
update_mode=GridUpdateMode.MODEL_CHANGED,
# needed for js injection
allow_unsafe_jscode=True
)
# Define dummy data
rng = np.random.default_rng(2021)
N_SAMPLES = 100
N_FEATURES = 10
df = pd.DataFrame(rng.integers(0, N_SAMPLES, size=(
N_SAMPLES, N_FEATURES)), columns=list(string.ascii_uppercase[:N_FEATURES]))
st.info("Select a row to remove it")
response = display_table(df)
st.write(f"Dataframe shape: {response['data'].shape}")
Genius, That sounds promising. Any idea what would be the event of Update button click? . Then I can set it to the grid options instead of onRowSelected event.
Hi @PablocFonseca, thanks for all your work, it’s super useful!
I’m struggling with columns formatting. I’m not able to format columns as percentages, and not able to have a thousand separators for numbers. Do you have a solution for this?
Thanks a lot!
To get comma separators (or full stop separators depending on locale (i.e. your browser’s language settings)), using the gridbuilder package as in the examples, for the column you’re talking about try something like:
I believe it should work in most browsers. As for percentages, I often use percentages in column headings for ease, but it can help readability so it’s understandable to want them within the table! If your number is between 0 and 1, to show as a percentage use something like: