| name | format-validity |
| description | Validate format of medical codes (ICD-9/10/11, SNOMED-CT, RxNorm, LOINC, ATC) in a QUIQ-format table. Identifies code type from variable name/description, then validates each value against the corresponding regex. Use for data quality assessment of medical code fields. |
Format Validity
Validates the format of medical codes in a QUIQ-format table. Targets rows where Mapping_info_1 = 'medical_code', identifies the code system (e.g. ICD-10), and checks whether each value matches the expected format via regex.
When to Use This Skill
- After QUIQ conversion, to verify that medical codes follow standard format rules
- To detect malformed ICD codes, LOINC codes, etc.
- As part of LYDUS quality management assessment
Supported Code Types
| Code System | Regex Pattern | Detection Keywords |
|---|
| ICD-9 | ^[0-9]{3}(\.[0-9]{1,2})?$ | icd + 9 |
| ICD-10 | ^[A-Z]{1}[0-9]{2}(\.[0-9]{1,2})?$ | icd + 10 |
| ICD-11 | ^[A-Z0-9][A-Z][0-9][A-Z0-9](\.[A-Z0-9]{1,2})?$ | icd + 11 |
| SNOMED-CT | ^[0-9]{6,18}$ | snomed + ct |
| RxNorm | ^[0-9]{5,9}$ | rxnorm |
| LOINC | ^[0-9]{1,6}-[0-9]{1}$ | loinc |
| ATC | ^[A-Z][0-9]{2}[A-Z]{2}[0-9]{2}$ | atc |
Unknown code types โ Is_valid = NULL (SQL) or Is_valid = False (Python without LLM)
Validation Pipeline
1. ๊ท์น ๊ธฐ๋ฐ (match_code_regex)
Variable_name + VIA Description ์์ ํค์๋ ํ์ง โ regex ๋ฐํ
2. LLM fallback (์ ํ, llm_define_regex)
๊ท์น์ผ๋ก ๋ฏธ๋ถ๋ฅ ์ Claude CLI์ ์ฝ๋๋ช
+ regex ์ง์
3. regex ๊ฒ์ฆ
๊ฐ Value์ str.match(regex) ์ ์ฉ
Output
| File | Description |
|---|
format_validity_total.txt | Overall Format Validity (%), Total/Invalid codes |
format_validity_summary.csv | Per-variable: Total_code, Invalid_code, Format_Validity (%), Regular_Expression |
format_validity_detail.csv | Per-row: Value, Is_valid |
How to Run
SQL ๋ฒ์ (๊ท์น ๊ธฐ๋ฐ๋ง, LLM ์์)
import os
import duckdb
skill_dir = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(skill_dir, "scripts/duckdb.sql")) as f:
sql = f.read()
quiq_csv = "/path/to/quiq_3patients.csv"
via_csv = "/path/to/via.csv"
sql = sql.replace("{quiq_csv}", quiq_csv)
sql = sql.replace("{via_csv}", via_csv)
df = duckdb.sql(sql).df()
total_code = df["Total_code"].sum()
invalid_code = df["Invalid_code"].sum()
format_validity = round((total_code - invalid_code) / total_code * 100, 2)
print(f"Format Validity (%) = {format_validity}")
save_path = "/path/to/output"
os.makedirs(save_path, exist_ok=True)
df.to_csv(f"{save_path}/format_validity_summary.csv", index=False, encoding="utf-8-sig")
with open(f"{save_path}/format_validity_total.txt", "w") as f:
f.write(f"Format Validity (%) = {format_validity}\n")
f.write(f"Total Code = {total_code}\n")
f.write(f"Invalid Code = {invalid_code}\n")
print(f"Saved {len(df):,} rows โ {save_path}")
Python ๋ฒ์ (LLM fallback ํฌํจ)
quiq_path: /path/to/quiq.csv
via_path: /path/to/via.csv
save_path: /path/to/output
use_llm: true
python scripts/format_validity.py --config config.yaml
Critical Notes
-
VIA ์์ด SQL ์คํ โ {via_csv} ์๋ฆฌ์ ํค๋๋ง ์๋ ๋น CSV๋ฅผ ๋ฃ์ผ๋ฉด Variable_name ๊ธฐ๋ฐ ํค์๋ ๋งค์นญ๋ง ๋์ํจ.
Original_table_name,Variable_name,Description
-
์๋ณธ ์ฝ๋ ๋ฒ๊ทธ ์์ โ ์ง๊ณ ์ Invalid_code = sum(Is_valid) (valid count) ๋ก ๊ณ์ฐํ ๋ค ๋์ค์ total - valid ๋ก ์ญ์ฐํ๋ ํผ๋์ค๋ฌ์ด ๋ก์ง โ Python ๋ฒ์ ์์ Valid_code / Invalid_code ๋ช
ํํ ๋ถ๋ฆฌ.
-
์ ์ํ float ์ฒ๋ฆฌ โ 4019.0 ๊ฐ์ ๊ฐ์ '4019' ๋ก ๋ณํ ํ ๊ฒ์ฆ (SQL: regex ๋ก ์ฒ๋ฆฌ, Python: str(int(x))).
-
Unknown ์ฝ๋ โ SQL ๋ฒ์ ์์ 7์ข
์ธ ์ฝ๋๋ Unknown_code ์ปฌ๋ผ์ผ๋ก ์ง๊ณ๋จ. LLM fallback ์์ด๋ format validity ๊ณ์ฐ์์ ์ ์ธ๋จ.
References
- LYDUS ํ์ง๊ด๋ฆฌ ํ๋ก๊ทธ๋จ ํ์ฉ ๊ฐ์ด๋๋ผ์ธ (๋น๊ณต๊ฐ ๋ด๋ถ ๋ฌธ์)
- Original Python implementation: LYDUS_Format_Validity.py (์ด์ฑ๋ฏผ ์์ฑ)