健康診断指標トレンド分析システム
用途
複数年度、複数形式(電子PDF / スキャン文書 / 写真)の健康診断レポートを統一した指標時系列に解析し、トレンド分析レポート + インタラクティブな健康管理ワークベンチを生成します。完全ローカル処理、自動的に個人情報をマスクし、動的に拡張可能(新しいレポートを追加したらパイプラインを再実行するだけです)。
トリガーワード
- 過去の健康診断レポート / 複数年度の健康診断レポート / 過去の健康診断
- 健康診断データのデジタル化 / 健康診断データ解析 / 健康診断レポート解析
- 健康診断指標の傾向 / 指標傾向分析 / 指標傾向
- 過去の健康診断指標比較 / 健康診断指標比較 / 経年比較 / 経年変化
- 検査結果分析 / 検査結果の読み解き / 検査レポート分析
- 健康診断レポートスキャン / スキャン版健康診断レポート / スキャンOCR
- 健康診断レポート写真 / 写真版健康診断レポート / スマホで撮影した健康診断レポート
- 健康管理ワークベンチ / 健康管理ダッシュボード / 健康データダッシュボード / 可視化ダッシュボード
- 血糖値トレンド / 血糖値変化 / 尿酸値高値 / 脂質トレンド / 血圧トレンド
- 健康診断異常指標 / 異常指標の読み解き / 指標異常
- 新しい健康診断レポート追加 / 新レポート取り込み / 新しい年の健康診断を追加
- 健康診断データ匿名化 / 匿名化データセット / 匿名化版 / 共有可能データセット
環境準備
# 依存関係(インストール済みの場合はスキップ可能):pymupdf 必須;Pillow(写真合成)、pyobjc-framework-Vision/Quartz(OCR、macOSのみ)オプション
export REPORT_DIR=/path/to/検査レポートディレクトリ # レポート格納ディレクトリ(PDF、または年度フォルダ+JPG)
export WORK_DIR=/path/to/作業データディレクトリ # データ成果物ディレクトリ(自動で data/ と output/ を作成)
export PY=/path/to/python # 依存関係のあるpythonインタプリタを推奨
Step 0(新しいセッションの最初のステップ、必須):
$PY scripts/check_deps.py # ワンクリックで依存関係チェック:何が不足か、どのスクリプトに影響するか、インストール方法
$PY scripts/check_deps.py --json # 機械可読、自動化での利用向け
終了コード 0 = 必須の依存関係全て揃っており作業開始可能;1 = 必須の依存関係不足(メインフローが実行不可、指示に従いインストール);オプションの依存関係不足は対応する入力形式にのみ影響し、電子版PDFのメインパスはブロックしません。
実行フロー
すべてのスクリプトは --help に対応しており、引数は環境変数より優先されます。引数なしで実行すると、環境変数のデフォルト動作が適用されます。
- 入力形式の識別:
REPORT_DIRを走査- ルートディレクトリの
*.pdfにテキストレイヤーがある場合 → 電子版(parse_reports.pyで処理) - ルートディレクトリの
*.pdfにテキストレイヤーがない場合 → スキャン文書(vision_ocr.py+extract.py) - 年度別サブディレクトリ
YYYY検査レポート/*.JPGの場合 → 写真版(make_year_pdfs.pyで合成 → OCR →extract.py)
- ルートディレクトリの
- 電子版PDFの解析(座標位置指定法、列境界は
references/解析と口径.mdを参照):$PY scripts/parse_reports.py # → data/reports_raw.json $PY scripts/parse_reports.py --year 2027 --dry-run # 単年テスト実行、ディスクには書き込まない - 写真版のPDF合成 + OCR + 抽出(JPGディレクトリ/スキャン文書が存在する場合):
$PY scripts/make_year_pdfs.py --year 2015-2020 # 年度ごとの複数JPG → 単一PDF(横向き撮影は自動回転補正) $PY scripts/vision_ocr.py <pdf> data/ocr_2022.json # スキャン文書/写真OCR → 座標付きJSON $PY scripts/extract.py --year 2022 # OCR結果 → 指標(戦略は自動判定) $PY scripts/extract.py --years 2015-2020 # 複数年のdict型OCR(略語+参照範囲から逆算)extract.pyは年パラメータ化されており、新しい年を追加してもコード変更は不要:data/ocr_<年>.jsonに配置後、直接--year <年>を指定します。 戦略のデフォルトはauto(入力JSONのトップレベルが dict →abbr、list →row)、--strategyで強制指定可能です。 - 正規化 + データセット構築(名称/単位マッピング、ダーティデータフィルタリング、OCR自動注入、匿名化版生成):
生成物$PY scripts/build_dataset.pydata/dataset_std.json(完全版、ローカル管理)+data/anonymized/anonymized_dataset_anon_shareable.json(匿名化版、独立サブディレクトリ + 読み取り専用444 + 共有可能) - 傾向分析(当年の基準範囲に基づく異常判定、有意な変化 ≥20% または ≥基準幅の30%、改善/悪化、直近3年に焦点):
$PY scripts/trend_analysis.py # デフォルトは直近3年 $PY scripts/trend_analysis.py --focus-years 2020,2023,2026 - 成果物の生成:
$PY scripts/report_generator.py # output/健康診断指標トレンド分析レポート.md(デフォルトで本文の匿名化が**有効**) $PY scripts/build_dashboard.py # output/health_dashboard.html(単一ファイル、オフライン対応)
新しいレポート取り込みガイド
新しい年度の健康診断レポートを追加する場合、形式に応じて該当するブランチを実行します(詳細は references/新レポート取り込みガイド.md を参照):
- レポートを配置:
REPORT_DIRのルートディレクトリに*.pdfを置くか、年度ディレクトリYYYY検査レポート/を作成してJPGを置く - 形式を識別:PDFのテキストレイヤーを確認(
get_text()の長さ >0 = 電子版)- 電子版 → 直接
parse_reports.pyを実行;列境界が異常な場合は先に1ページ分の座標サンプルを出力 - スキャン文書/写真 →
make_year_pdfs.py→vision_ocr.py→extract.py --year <年>(年ごとに新しいスクリプトを作成しない)
- 電子版 → 直接
- 辞書の補完(未収録の指標がある場合):
indicator_dict.pyのNAME_MAPに1行マッピングを追加(ログはdata/unrecognizedを参照)$PY scripts/indicator_dict.py --search 尿酸 # 既に収録されているか確認(別名を含む) $PY scripts/indicator_dict.py --validate # 辞書の整合性を自己チェック(ぶら下がりエイリアス/重複キー) $PY scripts/indicator_dict.py --count # 現在の標準指標総数 - パイプラインを再実行:build_dataset → trend_analysis → report_generator → build_dashboard
- 検収:新しい年が
trend_analysis.json["years"]とダッシュボードのタイムラインに含まれていることを確認;重要な指標3つをランダムに選び、値がレポートと一致することを確認;匿名化版を生成し検証
重要なルール
- プライバシーに関する厳格な制約(ゼロトレランス):すべてローカルで処理、スキル内に外部へのネットワーク呼び出しは一切含まれません;タスク完了時には必ず匿名化版を生成し検証します(氏名/ID番号/電話番号/住所/病院名を含まないこと)。共有には
data/anonymized/anonymized_dataset_anon_shareable.jsonのみを使用します(完全版dataset_std.jsonとは別ディレクトリで強固に分離、読み取り専用444、誤って完全版を共有するのを防止) - 匿名化検証はディスク書き込みよりも先に行う:
build_dataset.pyの_write_anon_verified()は匿名化版をディスクに書き込む唯一の出口です。まずメモリ上で検証し、合格した場合のみディスクに書き込みます。匿名化版は書き込みと同時に読み取り専用444に設定されます。もし書き込み後に検証していた場合、個人情報が含まれるファイルが既にディスクに残り、変更もできないまま[FAIL]が事後警告として表示されるだけになります。この出口を迂回して直接_write_anon()を呼び出すことは禁止されています;--skip-verifyは調査目的のみで使用し、成果物を共有してはいけません - レポート本文の匿名化:
report_generator.pyのmask_identity_textはデフォルトで有効(機関名、医師名、電話番号、ID番号をマスク);--no-maskでのみ無効化、ローカルでの原文確認用のみで、成果物は決して共有しないでください - 新しい年度のレポート追加:
REPORT_DIRに配置 → ステップ2→6を再実行するだけ;辞書に未収録の指標はdata/unrecognizedに記録され、indicator_dict.pyのNAME_MAPに1行追加するだけで対応 - OCRデータの位置づけ:OCRで抽出した指標はグラフ表示(灰色の Ⓞ マーク)のみに使用し、有意な変化の判定には使用しません。統計への悪影響を防ぐためです
- トレンドの焦点:全体トレンドと初回/最終比較は焦点年のみを基に行います(デフォルトは直近3年、
--focus-yearsでオーバーライド可能)。過去のデータは背景表示のみ - 基準範囲の一貫性:異常判定には当年のレポートに記載された参照範囲を使用します(試薬変更に自動対応。例:直接ビリルビン 2025年以降 0.0–4.0 → 1.7–6.8)
成果物
output/健康診断指標トレンド分析レポート.md— 指標集計表、異常ハイライト、信頼できる情報源に基づく解説、段階別アドバイス(生活習慣/食事/運動/受診基準)、方法論output/health_dashboard.html— 健康概要、改善/悪化グループフィルタリング、折れ線グラフ+参照範囲バンド、期間切替(単一ファイル、外部依存なし)data/anonymized/anonymized_dataset_anon_shareable.json— 共有可能な匿名化データセット
スクリプト一覧
| スクリプト | 用途 | 主なパラメータ |
|---|---|---|
check_deps.py | 依存関係自己チェック(Step 0) | --json --quiet |
parse_reports.py | 電子版PDF解析 | --report-dir --data-dir --year --out --dry-run |
make_year_pdfs.py | 年度別JPG → PDF | --report-dir --year --out-dir --dry-run |
vision_ocr.py | スキャン文書/写真OCR | pdf out(位置パラメータ)--dpi --quiet |
extract.py | OCR結果 → 指標(パラメータ化) | --year --strategy --ocr-json --out --data-dir --quiet |
build_dataset.py | 正規化 + 匿名化版 | --work-dir --data-dir --out --skip-verify --dry-run |
trend_analysis.py | トレンド判定 | --work-dir --focus-years --out --dry-run |
report_generator.py | Markdownレポート | --work-dir --out --no-mask --dry-run |
build_dashboard.py | HTMLワークベンチ | --work-dir --data-dir --out --quiet |
indicator_dict.py | 指標辞書(importされる) | --list --search --count --validate --category(直接実行時のみ有効) |
終了コードは3状態統一:0 成功 / 1 実行時エラー / 2 パラメータまたは前提条件未達。
参考ドキュメント
| ドキュメント | 内容 |
|---|---|
references/新レポート取り込みガイド.md | 新しい形式/年のレポート取り込みの完全な手順とトラブルシューティング |
references/解析と口径.md | 電子版PDFの列境界座標、口径定義 |
references/OCR方法論.md | スキャン文書/写真OCR戦略、略語マッピングテーブルのメンテナンス |
evals/ | 8件の回帰評価(プライバシー防衛線3件を含む)、eval_loop.py --run で実行可能 |
使用例(完全なセッション)
ユーザー:「2027年の健康診断レポートを追加して、トレンド分析を更新して。」
- Step 0:
python3 scripts/check_deps.py→ 必須の依存関係はすべて揃っている REPORT_DIRを確認:新しいファイル検査レポート_270510004567.pdf(電子版、テキストレイヤー完全)を発見- 小サンプルで列境界を確認:1ページ分の座標を出力、
references/解析と口径.mdと一致 → 調整不要 - パイプラインを実行:
export REPORT_DIR=検査レポート WORK_DIR=/path/to/work python3 scripts/parse_reports.py python3 scripts/build_dataset.py python3 scripts/trend_analysis.py python3 scripts/report_generator.py python3 scripts/build_dashboard.py - パースログに表示:新しい年度 98項目の指標、1つの未認識名 →
indicator_dict.py --searchで未収録を確認、NAME_MAPに1行追加して build_dataset を再実行 - 検収:
trend_analysis.json["years"]に2027が含まれている;ダッシュボードのタイムラインに2027が表示;血糖/脂質/BMIの値をランダムにチェックしレポートと一致;grepで匿名化版に個人情報がないことを確認 - 納品:レポート + ダッシュボードのパスをユーザーに通知;2027年の各異常指標の変化とアドバイスを説明
コスト削減の規律(実行時に強制)
- 小サンプル先行:新しい形式を解析する前に、まず1ページ分の座標サンプルを出力して列境界を確認してから全量処理(ファイル全体をダンプしない)
- 出力の圧縮:デバッグコマンドは一律
| head -N/python -cで正確に抽出、大きなJSONファイル全体をcatしない - サブエージェントの分離:大きなファイルの読み込みや形式の検出はExploreサブエージェントに任せ、メインスレッドは結論のみを受け取る
- 検証は最終スクリーンショット1回のみ、中間イテレーションではDOM/JSチェックで代用
変更履歴
| バージョン | 日付 | 変更内容 |
|---|---|---|
| 1.1.0 | 2026-08-29 | エンジニアリング集中改善:① 全10スクリプトが --help + argparse + 終了コード3状態に対応(改善前 0/10、ワースト);② check_deps.py 依存関係自己チェックを新規追加しStep 0に組み込み;③ 年ハードコードされた extract_2015_2020.py / extract_2022.py をパラメータ化 extract.py --year に統合(新しい年の追加にコード変更不要、出力形式は旧スクリプトとフィールド単位で一致);④ ## トリガーワード セクション12項目 + evals/ 8件の回帰評価(プライバシー防衛線3件を含む)を新規追加;⑤ プライバシー修正:匿名化版を「先にメモリ検証、合格後にディスク書き込み」に変更(従来は書き込み後に検証していたため、個人情報を含むファイルが既にディスクに書き込まれ読み取り専用となり、[FAIL] は事後警告に過ぎなかった);⑥ trend_analysis.py の測定項目消失デッドコードを修正(measurement_items が追加後にリセットされる問題、keyによる重複除去に変更) |
| 1.0.3 | 2026-08-23 | P2 M-1 改善(スキルセキュリティ):匿名化版の強固な分離——anonymized_dataset.json → data/anonymized/anonymized_dataset_anon_shareable.json(独立サブディレクトリ + 読み取り専用444 + _anon_shareable 命名マーク)に変更、完全版と匿名化版の混在による誤共有を防止;build_dataset.py に _write_anon() を新規追加(tmp+replaceのアトミック書き込み + chmod 444);report_generatorのプライバシー声明パスを同期 |
| 1.0.2 | 2026-08-17 | P1改善:build_dataset.py 末尾に verify_anonymized 自動検証を追加(ID番号/電話番号/メール/病院名を正規表現でスキャン、ヒットしたらエラーで終了) |
| 1.0.1 | 2026-08-17 | P0改善:report_generator.py に mask_identity_text 匿名化関数を追加(電話番号/ID番号/医師名マスク + 機関名汎化)、概要/結論のテキスト表示レイヤーを匿名化;プライバシー声明と実際の出力を整合 |
| 1.0.0 | 2026-08-16 | 初版:健康診断指標トレンド分析システム |