# 医療データを正規化する方法

> チュートリアル：多くのソースからの医療データを、比較可能な一つの形式に変換します — LOINCルックアップ、UCUM単位、ISO日付、参照範囲、リトライ時の重複排除、および欧州ラボプロファイルに対する検証。

Source: https://developers.anpheros.com/ja/guides/normalize-medical-data

**医療データを正規化するとは、さまざまな形式で到着する値を、比較可能な一つの形式に変換することです。つまり、同じ検査には同じコード、同じ単位系、一つの形式の日付、参照範囲とソースを持つすべての値、そして重複がない状態にします。** このチュートリアルでは、データがHL7 FHIR R4レコードに到達する前に、LOINCおよびATCコードのルックアップ、UCUM単位の使用、曖昧な日付の拒否、範囲の保持、リトライ時の重複回避、そして欧州ラボプロファイルに対する結果のチェックを行う方法を示します。表示されるすべてのレスポンスは、Anpheros APIからのものです。

## なぜ重要なのか

同じHbA1cの結果が、「HbA1c 6.4 %」、「Hemoglobina glicozilata: 6.4」、「Glycated haemoglobin 46 mmol/mol」といった形式や、特定の検査機関のみが理解できる検査コードとして届くことがあります。これらが単一のコードと単一の単位になるまでは、以下の問題が発生します。

- 患者のHbA1cの経時変化を示すグラフには、関連性のない3本の線が表示されます。
- 「HbA1cが6.5 %超」というアラートは、2つの値を検出できません。
- AIモデルは、1つのトレンドではなく4つの事実として認識します。
- レコードを受信する別のシステムは、それを解釈できません。

正規化は、データがレコードに入力される時点（一度だけ）で行われるべきであり、後でそれを読み取るすべてのアプリケーションで行われるべきではありません。

## 正規化された値の構成要素

| 要素 | 正規化された形式 | 例 |
|---|---|---|
| 測定対象 | 標準システムからのコード | LOINC `4548-4` (HbA1c)、RxNorm `6809` (メトホルミン)、ICD-10 `E11` (2型糖尿病) |
| 値 | 数値、または結果が数値でない場合のテキストのみ | `6.4` |
| 単位 | UCUM | `%`、`mg/dL`、`mm[Hg]`、`kg` |
| 時刻 | ISO 8601 日時、時刻が重要な場合はタイムゾーン付き | `2026-10-01T07:30:00Z` |
| 基準範囲 | 低値と高値、同じ単位で | `4.0`–`5.6` |
| ソース | 作成者とシステム | `import` from `labx` |
| 識別子 | 繰り返しを認識可能にするもの | 一意性キーまたはソース識別子 |

どのコードシステムがどのリソースタイプに対応するかは、[FHIR コードシステム](https://developers.anpheros.com/ja/guides/fhir-code-systems) に記載されています。

## ステップ 1: コードの検索

プラットフォームの用語を、英語またはルーマニア語の名前、あるいは略称で検索します。

```bash
curl "https://platform.anpheros.com/v1/terminology/loinc?q=hba1c" -H "Authorization: Bearer $KEY"
curl "https://platform.anpheros.com/v1/terminology/loinc?q=hemoglobina%20glicozilata" -H "Authorization: Bearer $KEY"
```

どちらの検索でも、同じコンセプトが返されます。

```json
{"data": [{"system": "http://loinc.org", "code": "4548-4", "display": "Hemoglobin A1c/Hemoglobin.total in Blood",
           "display_ro": "Hemoglobină glicozilată (HbA1c)", "category": "laboratory", "unit": "%"}], "total": 1}
```

医薬品については、[Anpheros Search](https://developers.anpheros.com/ja/guides/anpheros-search) で名前またはブランド名で物質を検索し、RxNorm 成分コードと EMA 製品番号を取得できます。

```bash
curl "https://platform.anpheros.com/v1/search?q=metformin&type=treatment" -H "Authorization: Bearer $KEY"
```

`unit` フィールドは、その検査で LOINC が期待する単位です。これを使用して、受信したものを確認してください。各ソース固有の名前からコードへのマッピングは、ソースごとに一度だけ構築し、統合に保存してください。書き込み時に推測しないでください。名前が曖昧で、ソースのどこにも解決策がない場合は、マッピングせずにソースに問い合わせてください。[FHIR レコードへの検査結果のインポート方法](https://developers.anpheros.com/ja/guides/import-lab-results-fhir) では、マッピングされていない検査マーカーをどのように保持および報告するかを示しています。

## ステップ 2: コード、単位、範囲で記述する

```bash
curl -X POST "https://platform.anpheros.com/v1/patients/$PID/observations" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: application/json" -H "Idempotency-Key: lab-77-hba1c" -d '{
  "code": "4548-4", "category": "laboratory",
  "value": 6.4, "unit": "%", "effective_at": "2026-10-01T07:30:00Z",
  "reference_range": {"low": 4.0, "high": 5.6},
  "author_type": "import"
}'
```

```json
{"id": "3296315c-…", "code": "4548-4", "system": "http://loinc.org", "display": "Hemoglobin A1c/Hemoglobin.total in Blood",
 "category": "laboratory", "effective_at": "2026-10-01T07:30:00Z", "value": 6.4, "unit": "%",
 "reference_range": {"low": 4.0, "high": 5.6}, "status": "final", "fhir": "Observation/3296315c-…"}
```

コードのみを送信すると、プラットフォームはREST APIおよびFHIR API（`/fhir/R4`）で標準のLOINC名を補完するため、すべてのアプリケーションが同じ`display`を読み取ります。自分で送信した`display`はそのまま保持されます。

元の表現も維持してください。検査レポートの場合、FHIR Observationの`code.text`には、LOINCコーディングの横に検査機関の名前（「Hemoglobina glicozilata (HbA1c)」）が保持されます。患者は引き続き紙のレポートを認識でき、マッピングが疑問視された場合でも何も失われません。

## ステップ 3: 単位

UCUM コードを使用します: `mg/dL`, `mmol/L`, `%`, `mm[Hg]`, `kg`, `cm`, `/min`, `Cel`。ほとんどのエラーを防ぐ 2 つのルールがあります。

- **サイレント変換は行わないでください。** 検査機関が `mmol/L` でグルコースを報告し、アプリが `mg/dL` で表示する場合、検査機関が測定した値を保存し、表示時に変換してください。保存された値はレポートに追跡可能のままです。
- **コードに対して単位を確認してください。** LOINC コードは具体的です。`%` の HbA1c は `4548-4` ですが、`mmol/mol` の HbA1c は異なる LOINC コードです。単位がコードの期待される単位と一致しない値は、変換の問題ではなく、マッピングエラーです。

Anpheros は単位を自動的に変換しません。送信された単位をそのまま保存します。

## ステップ 4: 日付

書き込む前に、ソースの既知の形式を使用して、日付を ISO 8601 に変換します。`01.10.2026` はルーマニアや多くのヨーロッパ諸国では 10 月 1 日ですが、`10/01/2026` は米国では 10 月 1 日です。API は推測するのではなく、ISO 形式でないものは拒否します。

```json
{"error": {"type": "invalid", "message": "Input should be a valid datetime or date, invalid character in year (at effective_at)", "field": "effective_at"}}
```

ラボコネクタは例外です。ヨーロッパのレポートを読み取っていることを認識しているため、`DD.MM.YYYY` および `DD/MM/YYYY` を受け入れます。

一日の時間が重要な測定値（血圧、グルコース、投薬量）については、タイムゾーンとともに時間を送信してください。ブカレストの 23:30 の測定値は UTC では前日になりますが、患者は測定した日の日付を期待しています。

## ステップ 5: 重複の排除

重複は、リトライ、同じレポートの複数回送信、および複数の経路から同じ値が到着することによって発生します。

- **リトライ:** 値のソースを識別する `Idempotency-Key` を送信します。例えば、レポートIDとテストなどです。同じキーで同じリクエストを再度送信すると、最初の応答が返され、新しいものは何も保存されません。SDKは、すべての作成に対して1つ追加します。
- **同じレポートの複数回送信:** ラボコネクタは、レポート、コード、日付、値から行ごとに安定した識別子を構築し、既にインポートされた行はスキップします。
- **複数の経路:** ソースシステムのIDを `X-Anpheros-Origin-Id` (または FHIR リソースの `identifier`) に保存し、別のパスから戻ってくる可能性のある値を書き込む前に検索します。

## ステップ 6: プロファイルとの照合

検査結果については、リソースがHL7 Europe 検査レポートプロファイルにどの程度適合するかをプラットフォームに問い合わせてから、そのリソースを信頼してください。

```bash
curl -X POST "https://platform.anpheros.com/fhir/R4/Observation/\$validate?profile=eu-lab" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: application/fhir+json" -d '{
  "resourceType": "Observation", "status": "final",
  "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "laboratory"}]}],
  "code": {"text": "HbA1c"}, "subject": {"reference": "Patient/'$PID'"},
  "valueQuantity": {"value": 6.4, "unit": "%"}
}'
```

この正規化されていない結果は、正確なリストを取得します。

```json
{"resourceType": "OperationOutcome", "issue": [
  {"severity": "error", "code": "invalid", "diagnostics": "Observation.code must carry a LOINC coding.", "expression": ["Observation.code"]},
  {"severity": "error", "code": "required", "diagnostics": "Observation.effective[x] is required.", "expression": ["Observation.effective"]},
  {"severity": "warning", "code": "business-rule", "diagnostics": "valueQuantity should carry a UCUM system and code.", "expression": ["Observation.valueQuantity"]},
  {"severity": "warning", "code": "informational", "diagnostics": "No referenceRange: interpretation will need the laboratory's ranges.", "expression": ["Observation.referenceRange"]},
  {"severity": "information", "code": "informational", "diagnostics": "No performer (laboratory) recorded.", "expression": ["Observation.performer"]},
  {"severity": "information", "code": "informational", "diagnostics": "No issued time (when the laboratory released the result).", "expression": ["Observation.issued"]}]}
```

各問題は上記のステップのいずれかに対応します。各ソースからの実際のサンプルを使用して、統合テストで`$validate`を実行してください。

## ステップ 7: ソースの保持

正規化は値の書き方を変えることはありますが、その出所を変えることはありません。書き込み時には常に`author_type`（`device`、`import`、`practitioner`、`patient`）と`X-Anpheros-Source-System`を送信してください。これにより、医師、監査担当者、またはAIモデルが、自宅で入力された値と検査室の結果を区別できるようになります。[Medical data provenance explained](https://developers.anpheros.com/guides/medical-data-provenance) を参照してください。

## チェックリスト

- [ ] 各ソースについて、その名称からLOINC / ATC / ICD-10へのマッピングを統合先に保持すること
- [ ] 名前が曖昧なものはマッピングせず、報告すること。推測しないこと
- [ ] UCUM単位はコードと一致させること。サイレントな変換は行わないこと
- [ ] ISO 8601形式の日付を使用すること。時刻が重要な場合はタイムゾーンを含めること
- [ ] 検査値とともに参照範囲を保持すること
- [ ] 元の表記を保持すること (`code.text`)
- [ ] すべての書き込み操作で冪等性キーまたはソースIDを使用すること
- [ ] すべての書き込み操作で`author_type`およびソースシステムを使用すること
- [ ] 検査結果のテストでは`$validate`を使用すること

## よくある質問

### 医療データの正規化とは何ですか？
異なるソースからの健康データを1つの標準形式に変換することです。共有コード（検査および測定にはLOINC、診断にはICD-10、薬剤にはATC）、UCUM単位、ISO日付、参照範囲、および記録されたソースを含めることで、異なるシステムからの値を比較、結合、および交換できるようになります。

### すべての値を1つの単位に変換する必要がありますか？
ソースが測定した単位を、それがコードに一致する有効なUCUM単位である限り、保存し、表示または分析時に変換します。これにより、保存されたすべての値が元のレポートにトレーサブルになります。

### 正規化は完全に自動化できますか？
ほとんどの場合可能です。ソース内のコード、既知の名前、および適切にフォーマットされた単位は自動的にマッピングできます。曖昧な名前と未知のローカルコードは、ソースごとに1回人間の判断が必要ですが、その後はマッピングが自動化されます。

## 関連情報

- [FHIR コードシステム](https://developers.anpheros.com/ja/guides/fhir-code-systems)
- [FHIR レコードへの検査結果のインポート方法](https://developers.anpheros.com/ja/guides/import-lab-results-fhir)
- [医療データプロベナンスの説明](https://developers.anpheros.com/guides/medical-data-provenance)
- [ヘルスケアデータの相互運用性](https://developers.anpheros.com/ja/guides/interoperability)
- [医療データ API](https://developers.anpheros.com/ja/guides/medical-data-api)
