streamlitのdataframeで特定の行のスタイルを変更したいとき

こんにちは、ナナオです。 今回は小ネタです。 実装 streamlitでも、pandasのDataFrameのスタイルが証できるのでこれを使って以下のように実装します。 実装では特定のカラム(target)の値が10より大きい場合に赤い太字で表示するようにしています。 import pandas as pd import streamlit as st def highlight_overdue(row): # int64をpythonのint型に変換 target = row["target"].item() # targetが10より大きい場合に赤の太字で表示する if isinstance(target, int) and target > 10: return ["color: red; font-weight: bold"] * len(row) else: return [""] * len(row) df = pd.DataFrame([ {"target": 1}, {"target": 2}, {"target": 4}, {"target": 8}, {"target": 16}, {"target": 32}, ]) df = df.style.apply(highlight_overdue, axis=1) st.dataframe(df, width="stretch") 実行すると以下のようになります。 感想 streamlitでスタイルも楽々変更できました。

2026年1月30日 · にあえん

図書館予約管理システムをk8sでデプロイする

こんにちは、ナナオです。 以前の記事で図書館予約管理システムの構築と自宅k8sサーバーの構築を行いました。 Seleniumで図書館の予約管理システムを作った streamlitで表を出力した おうちでk3sを使ってk8sを構築する 今回は構築したk8s環境に予約システムをデプロイしようと思います。 実装 まずはDockerイメージのプッシュです。 Dockerレジストリを何にしようか…というのが最初のポイントですが、docker.ioはプライベートリポジトリが1リポジトリしか使えないのでナシ。 ghcr.ioは自分がGithubアカウントがプロなのもあって2GBまでストレージ使えるのと月の通信量が10GBまでなら課金なしなので、ghcr.ioにします。 ということでイメージをビルドしていきます。 docker build -f docker/Dockerfile -t library-checker:0.1.0 . プッシュもやっちゃいましょう。 ここからはこのドキュメントを参照します。 https://docs.github.com/ja/packages/working-with-a-github-packages-registry/working-with-the-container-registry GitHub Container Registry(ghcr)でコンテナイメージを管理する #Docker - Qiita PATを発行し、以下のコマンドを実行します。 echo "<発行したPAT>" | docker login ghcr.io -u <username> --password-stdin ログインに成功したら、以下のコマンドでプッシュします。 docker push ghcr.io/NAMESPACE/IMAGE_NAME:latest 次にイメージのプルに必要な認証情報をクラスタに渡します。 kubectl create secret docker-registry ghcr-secret \ --docker-server=https://ghcr.io \ --docker-username=ユーザー名 \ --docker-password=PAT(ghp_xxxx...) \ --docker-email=メールアドレス また、定義していた.envもシークレットとして登録しておきます。 kubectl create secret generic library-checker-env --from-env-file=.env それでは、システムを動かすためのファイルを実装します。 apiVersion: apps/v1 kind: Deployment metadata: name: library-checker spec: replicas: 1 selector: matchLabels: app: library-checker template: metadata: labels: app: library-checker spec: imagePullSecrets: - name: ghcr-secret # 先ほどクラスタに設定したイメージのプルに必要な認証情報 containers: # --- 1. アプリ本体 (Streamlit等のUIを想定) --- - name: app image: ghcr.io/<ユーザー名>/library-checker:0.1.0 ports: - containerPort: 8501 env: - name: SELENIUM_URL value: "http://localhost:4444" # 同じPod内なのでlocalhostでOK # .envの内容は本来ConfigMapやSecretを使いますが、一旦直接指定か環境変数で対応 envFrom: - secretRef: name: library-checker-env # 先ほどデプロイしたシークレット # 生存確認 readinessProbe: httpGet: path: /healthz port: 8501 initialDelaySeconds: 5 periodSeconds: 5 livenessProbe: httpGet: path: /healthz port: 8501 initialDelaySeconds: 10 periodSeconds: 5 # --- 2. Selenium Chrome (サイドカー) --- - name: chrome image: selenium/standalone-chrome:4.39.0-20251212 ports: - containerPort: 4444 resources: limits: memory: "2Gi" cpu: "1000m" volumeMounts: - name: dshm mountPath: /dev/shm # 共有メモリ (/dev/shm) の不足によるクラッシュを防ぐ設定 volumes: - name: dshm emptyDir: medium: Memory --- # --- 3. 外部公開用サービス --- apiVersion: v1 kind: Service metadata: name: library-checker-service spec: type: NodePort selector: app: library-checker ports: - name: ui port: 8501 targetPort: 8501 nodePort: 30501 # 外部からアクセスするポート - name: selenium port: 4444 targetPort: 4444 nodePort: 30444 今回もGemini先生に頑張ってもらいました。 ...

2026年1月13日 · にあえん

streamlitで表を出力した

こんにちは、ナナオです。 前回の記事で図書館の予約管理システムを構築しました。 データ取得まではできましたが、データ出力するところが実装できなかったので今回実装していこうと思います。 React使うか~とかも思ったのですが、Geminiと相談した結果Streamlitというライブラリを使うことにしました。 Streamlitとは グラフデータや表データなどを含むWebアプリを超簡単に構築できるライブラリです。 Streamlit • A faster way to build and share data apps もちろん自由度はReactでフロントエンドを作るよりも低くはなるのですが、大体の機能が揃っているのでとりあえずデータ出力したいだけであればこれで十分だと思います。 実装 ということで実装していきます。 今回は以下のデータクラスを表で出力します。 @dataclass class LoanStatusItem: deadline_at: dt.date borrower_name: str library_name: str book_title: str @dataclass class ReserveItem: status: Literal["reserved", "already"] borrower_name: str library_name: str book_title: str 必要なライブラリを追加します。 uv add streamlit pandas 実装はとりあえずダミーデータを使ってやりました。 def get_dummy_data(): # 貸出状況のデータ loans = [ LoanStatusItem(dt.date(2023, 10, 15), "佐藤", "中央図書館", "Python入門"), LoanStatusItem(dt.date(2023, 10, 20), "鈴木", "北図書館", "Streamlit実践"), LoanStatusItem(dt.date(2023, 10, 12), "佐藤", "中央図書館", "機械学習の基礎"), ] # 予約状況のデータ reserves = [ ReserveItem("reserved", "佐藤", "南図書館", "Web設計パターン"), ReserveItem("already", "田中", "中央図書館", "デザイン思考"), ReserveItem("reserved", "鈴木", "北図書館", "Docker活用"), ] current_time = dt.datetime.now().strftime('%H:%M:%S') return loans, reserves, current_time def main(): st.title("図書館 利用状況ダッシュボード") # --- 更新ボタンの配置 --- # col1, col2 を使うことで、タイトルやボタンの配置を調整できます col1, col2 = st.columns([3, 1]) with col1: st.write("最新の貸出・予約状況を表示します。") with col2: # ボタンが押されたらキャッシュをクリアして再実行 if st.button("最新情報を取得 🔄"): st.cache_data.clear() # キャッシュを削除 st.rerun() # スクリプトを再実行(画面更新) # データの取得 loans, reserves, fetched_time = get_dummy_data() # 更新時刻の表示 st.caption(f"データ取得時刻: {fetched_time}") # --- 1. 貸出状況の表示 --- st.subheader("📅 貸出状況 (Loan Status)") if loans: # dataclassのリストをDataFrameに変換 # dataclasses.asdictを使うと辞書に変換され、DataFrame化しやすくなります df_loans = pd.DataFrame([asdict(item) for item in loans]) # カラム名の見た目を整える(任意) df_loans = df_loans.rename(columns={ "deadline_at": "返却期限", "borrower_name": "利用者名", "library_name": "図書館", "book_title": "書名" }) # テーブル表示 (use_container_width=Trueで横幅いっぱいに表示) st.dataframe(df_loans, use_container_width=True) else: st.info("貸出中の本はありません。") st.markdown("---") # 区切り線 # --- 2. 予約状況の表示 --- st.subheader("🔖 予約状況 (Reserve Status)") if reserves: df_reserves = pd.DataFrame([asdict(item) for item in reserves]) # カラム名の整理 df_reserves = df_reserves.rename(columns={ "status": "状態", "borrower_name": "利用者名", "library_name": "図書館", "book_title": "書名" }) # 状態(reserved/already)に応じて色をつけたりも可能です st.dataframe(df_reserves, use_container_width=True) else: st.info("予約中の本はありません。") if __name__ == "__main__": main() これを実行します。 ...

2026年1月8日 · にあえん