Streamlitで高機能テーブルを実装したい方へ📊 AgGridを使うとExcel風の編集機能やフィルター、ソート機能などが簡単に実装できます。初心者向けに基本から行の追加・削除までをまとめてみました。🙏
はじめに
Streamlitでデータ分析アプリを作る際、標準のテーブル表示では機能が不足しがちです。特にExcelのような編集機能やフィルタリング、ソート機能などが欲しい場合には「AgGrid」というライブラリが非常に便利です。この備忘録では、AgGridの基本的な使い方から、行の追加・削除などの操作を含めた実装方法をまとめています。
インストール方法
pip install streamlit-aggrid
基本的な使い方
AgGridを使ったExcel風の編集可能なグリッドを実装する完全なコード例を以下に示します。このコードには行の追加・削除といった基本的な操作も含まれています。
import streamlit as st
import pandas as pd
from st_aggrid import AgGrid, GridOptionsBuilder
# --------------------------------
# 1) セッションの初期化
# --------------------------------
if 'data' not in st.session_state:
st.session_state.data = pd.DataFrame({
"名前": ["佐藤", "鈴木", "田中"],
"業種": ["Technology", "Finance", "Healthcare"],
"評価": ["Hot", "Warm", "Cold"]
})
st.title("🧮 Excel風 入力グリッド(AgGrid)")
# --------------------------------
# 2) GridOptions の設定
# --------------------------------
gb = GridOptionsBuilder.from_dataframe(st.session_state.data)
gb.configure_default_column(
editable=True,
sorteable=True,
filterable=True,
resizable=True
)
# 行選択(複数行選択)を有効化
gb.configure_selection('multiple')
grid_options = gb.build()
# --------------------------------
# 3) AgGridの表示
# --------------------------------
grid_response = AgGrid(
st.session_state.data,
gridOptions=grid_options,
update_mode="MODEL_CHANGED",
fit_columns_on_grid_load=True,
allow_unsafe_jscode=True
)
# AgGrid から返されるデータをセッションに反映
if grid_response['data'] is not None:
st.session_state.data = grid_response['data']
# 選択された行をDataFrameとして取得
selected_rows_df = grid_response['selected_rows'] # ここが DataFrame 形式の場合の想定
# --------------------------------
# 4) ボタンによる行操作
# --------------------------------
col1, col2, col3 = st.columns(3)
# ------ (A) 行の追加 ------
with col1:
if st.button("➕ 行を追加"):
new_row = pd.DataFrame([{"名前": "", "業種": "", "評価": ""}])
st.session_state.data = pd.concat([st.session_state.data, new_row], ignore_index=True)
st.rerun()
# ------ (B) 選択行の削除 ------
with col2:
if st.button("🗑️ 選択行を削除"):
# ★ DataFrame判定で空かどうかを確認
if selected_rows_df is None or selected_rows_df.empty:
st.warning("削除する行が選択されていません")
else:
current_data = st.session_state.data.copy()
# 選択された行を 1 行ずつループして削除
# (DataFrameなので .iterrows() で回す)
for idx, row in selected_rows_df.iterrows():
# "名前","業種","評価" が一致する行を削除する例
mask = (
(current_data["名前"] == row["名前"]) &
(current_data["業種"] == row["業種"]) &
(current_data["評価"] == row["評価"])
)
current_data = current_data[~mask]
# 削除結果をセッションへ反映
st.session_state.data = current_data.reset_index(drop=True)
st.rerun()
# ------ (C) 保存ボタン ------
with col3:
if st.button("✅ 保存"):
st.success("データが保存されました")
st.write(st.session_state.data)
# ------ CSVエクスポート ------
csv_data = st.session_state.data.to_csv(index=False).encode("utf-8-sig")
st.download_button(
"📥 CSVエクスポート",
csv_data,
"aggrid_data.csv",
"text/csv",
key='download-csv'
)
コードの詳細解説
1. セッションの初期化
Streamlitはステートレスなフレームワークなので、ページがリロードされるたびに変数は初期化されます。そのため、データを保持するにはst.session_state
を使います。
if 'data' not in st.session_state:
st.session_state.data = pd.DataFrame({
"名前": ["佐藤", "鈴木", "田中"],
"業種": ["Technology", "Finance", "Healthcare"],
"評価": ["Hot", "Warm", "Cold"]
})
2. GridOptionsの設定
AgGridの挙動はGridOptionsで細かく設定できます。
gb = GridOptionsBuilder.from_dataframe(st.session_state.data)
gb.configure_default_column(
editable=True, # 編集可能にする
sorteable=True, # ソート可能にする
filterable=True, # フィルタリング可能にする
resizable=True # 列幅のリサイズを可能にする
)
# 行選択(複数行選択)を有効化
gb.configure_selection('multiple')
grid_options = gb.build()
-
editable=True
: セルを直接編集できるようにします -
sorteable=True
: 列ヘッダーをクリックしてソートできるようにします -
filterable=True
: 列ヘッダーのメニューからフィルタリングできるようにします -
resizable=True
: 列の幅を変更できるようにします -
configure_selection('multiple')
: 複数行の選択を可能にします
3. AgGridの表示
grid_response = AgGrid(
st.session_state.data,
gridOptions=grid_options,
update_mode="MODEL_CHANGED",
fit_columns_on_grid_load=True,
allow_unsafe_jscode=True
)
-
update_mode="MODEL_CHANGED"
: データモデルが変更されたときに更新します -
fit_columns_on_grid_load=True
: 初期表示時に列幅を自動調整します -
allow_unsafe_jscode=True
: JavaScript関数の実行を許可します(カスタムレンダラーなどに必要)
グリッド操作後のデータを取得して、セッションに保存します:
if grid_response['data'] is not None:
st.session_state.data = grid_response['data']
# 選択された行をDataFrameとして取得
selected_rows_df = grid_response['selected_rows']
4. ボタンによる行操作
(A) 行の追加
if st.button("➕ 行を追加"):
new_row = pd.DataFrame([{"名前": "", "業種": "", "評価": ""}])
st.session_state.data = pd.concat([st.session_state.data, new_row], ignore_index=True)
st.rerun()
空の行を作成し、現在のデータフレームに結合してから、ページを再読み込みします。
(B) 選択行の削除
if st.button("🗑️ 選択行を削除"):
# DataFrame判定で空かどうかを確認
if selected_rows_df is None or selected_rows_df.empty:
st.warning("削除する行が選択されていません")
else:
current_data = st.session_state.data.copy()
# 選択された行を1行ずつループして削除
for idx, row in selected_rows_df.iterrows():
mask = (
(current_data["名前"] == row["名前"]) &
(current_data["業種"] == row["業種"]) &
(current_data["評価"] == row["評価"])
)
current_data = current_data[~mask]
# 削除結果をセッションへ反映
st.session_state.data = current_data.reset_index(drop=True)
st.rerun()
選択された行の特定は、複数の列の値が一致する行を探すことで行っています。Pandasの条件式で一致する行を特定し、逆マスク(~mask
)で一致しない行だけを残します。
(C) 保存とエクスポート
if st.button("✅ 保存"):
st.success("データが保存されました")
st.write(st.session_state.data)
# CSVエクスポート
csv_data = st.session_state.data.to_csv(index=False).encode("utf-8-sig")
st.download_button(
"📥 CSVエクスポート",
csv_data,
"aggrid_data.csv",
"text/csv",
key='download-csv'
)
保存ボタンは現在の状態を表示するだけですが、実際のアプリケーションではデータベースやCSVファイルなどに保存する処理を追加します。
CSVエクスポート機能は、データフレームをCSV形式に変換してダウンロードボタンを表示します。
応用例
カスタム列設定
特定の列だけに異なる設定を適用したい場合:
# 特定の列設定
gb.configure_column("名前", editable=False) # 名前列は編集不可
gb.configure_column("評価",
editable=True,
cellEditor='agSelectCellEditor',
cellEditorParams={
'values': ['Hot', 'Warm', 'Cold']
}) # 評価列はドロップダウンリストから選択
条件付き書式
値に応じてセルの色を変更したい場合:
from st_aggrid import JsCode
# 条件付き書式
cellsytle_jscode = JsCode("""
function(params) {
if (params.value == 'Cold') {
return {
'color': 'white',
'backgroundColor': 'blue'
}
}
if (params.value == 'Hot') {
return {
'color': 'white',
'backgroundColor': 'red'
}
}
return {
'color': 'black',
'backgroundColor': 'yellow'
}
};
""")
gb.configure_column('評価', cellStyle=cellsytle_jscode)
ページネーション
大量のデータを扱う場合にはページネーションが便利です:
# ページネーション設定
gb.configure_grid_options(pagination=True, paginationAutoPageSize=True)
# または固定ページサイズ
# gb.configure_grid_options(pagination=True, paginationPageSize=10)
学習メモ・注意点
-
Streamlitのステートレス性:
- Streamlitはステートレスなので、ボタンをクリックするたびにスクリプト全体が再実行されます
- データを保持するには必ず
st.session_state
を使いましょう
-
型の扱い:
- Pandas DataFrameを条件式で直接評価すると「The truth value of a DataFrame is ambiguous」エラーになります
- 正しくは
if df is None or df.empty:
のように明示的にチェックします
-
行の削除:
- 複数の列を使って行を一意に特定することが重要です
- インデックスが予想と異なる場合があるので、値ベースでの比較が安全です
-
パフォーマンス:
- 大きなデータセットを扱う場合は、ページネーションを有効にしましょう
- フィルタリングやソートはクライアント側で行われるので、非常に大きなデータセットでは注意が必要です