Files
DeepHealth/build_uk_hfrs_label_mapping.py

216 lines
5.0 KiB
Python

from __future__ import annotations
import csv
from pathlib import Path
LABELS = Path("labels.csv")
OUT = Path("uk_hfrs_label_mapping.csv")
MISSING_OUT = Path("uk_hfrs_missing_label_codes.csv")
# Source: Gilbert T, Neuburger J, Kraindler J, et al. Development and
# validation of a Hospital Frailty Risk Score focusing on older people in
# acute care settings using electronic hospital records. Lancet. 2018.
# Supplementary appendix, Table A2.
UK_HFRS_WEIGHTS = {
"F00": 7.1,
"G81": 4.4,
"G30": 4.0,
"I69": 3.7,
"R29": 3.6,
"N39": 3.2,
"F05": 3.2,
"W19": 3.2,
"S00": 3.2,
"R31": 3.0,
"B96": 2.9,
"R41": 2.7,
"R26": 2.6,
"I67": 2.6,
"R56": 2.6,
"R40": 2.5,
"T83": 2.4,
"S06": 2.4,
"S42": 2.3,
"E87": 2.3,
"M25": 2.3,
"E86": 2.3,
"R54": 2.2,
"Z50": 2.1,
"F03": 2.1,
"W18": 2.1,
"Z75": 2.0,
"F01": 2.0,
"S80": 2.0,
"L03": 2.0,
"H54": 1.9,
"E53": 1.9,
"Z60": 1.8,
"G20": 1.8,
"R55": 1.8,
"S22": 1.8,
"K59": 1.8,
"N17": 1.8,
"L89": 1.7,
"Z22": 1.7,
"B95": 1.7,
"L97": 1.6,
"R44": 1.6,
"K26": 1.6,
"I95": 1.6,
"N19": 1.6,
"A41": 1.6,
"Z87": 1.5,
"J96": 1.5,
"X59": 1.5,
"M19": 1.5,
"G40": 1.5,
"M81": 1.4,
"S72": 1.4,
"S32": 1.4,
"E16": 1.4,
"R94": 1.4,
"N18": 1.4,
"R33": 1.3,
"R69": 1.3,
"N28": 1.3,
"R32": 1.2,
"G31": 1.2,
"Y95": 1.2,
"S09": 1.2,
"R45": 1.2,
"G45": 1.2,
"Z74": 1.1,
"M79": 1.1,
"W06": 1.1,
"S01": 1.1,
"A04": 1.1,
"A09": 1.1,
"J18": 1.1,
"J69": 1.0,
"R47": 1.0,
"E55": 1.0,
"Z93": 1.0,
"R02": 1.0,
"R63": 0.9,
"H91": 0.9,
"W10": 0.9,
"W01": 0.9,
"E05": 0.9,
"M41": 0.9,
"R13": 0.8,
"Z99": 0.8,
"U80": 0.8,
"M80": 0.8,
"K92": 0.8,
"I63": 0.8,
"N20": 0.7,
"F10": 0.7,
"Y84": 0.7,
"R00": 0.7,
"J22": 0.7,
"Z73": 0.6,
"R79": 0.6,
"Z91": 0.5,
"S51": 0.5,
"F32": 0.5,
"M48": 0.5,
"E83": 0.4,
"M15": 0.4,
"D64": 0.4,
"L08": 0.4,
"R11": 0.3,
"K52": 0.3,
"R50": 0.1,
}
def _read_labels(path: Path) -> list[dict[str, str | int]]:
rows: list[dict[str, str | int]] = []
with path.open(encoding="utf-8") as f:
for i, line in enumerate(f):
line = line.strip()
if not line:
continue
parts = line.split(maxsplit=1)
code = parts[0].strip().upper()
name = parts[1].strip() if len(parts) > 1 else ""
rows.append({"token_id": i + 3, "label_code": code, "label_name": name})
return rows
def main() -> None:
labels = _read_labels(LABELS)
label_codes = {str(row["label_code"]) for row in labels}
missing = sorted(set(UK_HFRS_WEIGHTS) - label_codes)
rows = []
for row in labels:
code = str(row["label_code"])
weight = float(UK_HFRS_WEIGHTS.get(code, 0.0))
rows.append(
{
**row,
"hfrs_dimension_id": "hfrs_weighted_disease_expression",
"hfrs_dimension": "DeepHealth HFRS-weighted disease expression",
"hfrs_key_area": "UK-HFRS",
"hfrs_weight": weight,
"hfrs_source": (
"Gilbert et al. Lancet 2018 supplementary appendix Table A2"
),
"match_source": "exact_three_character_icd10" if weight else "not_in_hfrs",
}
)
fieldnames = [
"token_id",
"label_code",
"label_name",
"hfrs_dimension_id",
"hfrs_dimension",
"hfrs_key_area",
"hfrs_weight",
"hfrs_source",
"match_source",
]
with OUT.open("w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
with MISSING_OUT.open("w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(
f,
fieldnames=[
"hfrs_source_code",
"hfrs_weight",
"missing_reason",
"hfrs_source",
],
)
writer.writeheader()
for code in missing:
writer.writerow(
{
"hfrs_source_code": code,
"hfrs_weight": UK_HFRS_WEIGHTS[code],
"missing_reason": "not_present_in_labels_csv",
"hfrs_source": (
"Gilbert et al. Lancet 2018 supplementary appendix Table A2"
),
}
)
nonzero = sum(1 for row in rows if float(row["hfrs_weight"]) != 0.0)
print(f"labels: {len(rows)}")
print(f"uk_hfrs_codes: {len(UK_HFRS_WEIGHTS)}")
print(f"matched_nonzero_labels: {nonzero}")
print(f"missing_hfrs_codes: {len(missing)}")
print(f"output: {OUT}")
print(f"missing_output: {MISSING_OUT}")
if __name__ == "__main__":
main()