Input and output
Input
One row per diagnosis, in long format:
| id | code | age | year |
|---|---|---|---|
| 1 | I21 | 66 | 2012 |
| 1 | E11.9 | 66 | 2012 |
| 2 | C349 | 81 | 2010 |
id_colandcode_colare required;age_col(Charlson) andyear_col(year-specific implementations, ICD modification) only where the score needs them. Age and year repeat on every row of a patient.- polars and pandas DataFrames are accepted. The result has the type of the input.
- Codes must be strings. Numeric columns are rejected with a
ValueError, because250.1and"250.10"are different ICD-9 codes. Categorical columns are converted.
How codes are matched
Codes are cleaned (dots removed, whitespace stripped, upper-cased) and then matched by prefix: the definition I21 matches I21, I219 and I21.9. A code belongs to every category that lists any of its prefixes. E11.9 and E119 are the same code. Missing and blank codes match nothing; their patients stay in the result with all categories 0.
Output
One row per patient:
| Score | Columns without return_categories |
Added by return_categories=True |
|---|---|---|
charlson |
id, Charlson Comorbidity Index, Charlson Age-Comorbidity Score |
one 0/1 column per category (before the index), Age Score |
elixhauser |
id, Elixhauser Comorbidity Index |
one 0/1 column per category |
combined |
id, Combined Comorbidity Score |
one 0/1 column per category |
hfrs |
id, HFRS Score |
one 0/1 column per category |
custom |
id, score_col_name |
one 0/1 column per category |
- The Charlson index is the sum of the category weights; the Age-Comorbidity Score adds the age points.
- Patients without a matching code are kept, with all categories 0.
- The row order of the result is not the order of the input. Sort or join on
idif you need an order.
Warnings and errors
| Type | Message | Cause |
|---|---|---|
ValueError |
Unknown score | score is not one of charlson, elixhauser, combined (gagne), hfrs, custom |
ValueError |
Column 'age' (age) must be present in input DataFrame for Charlson calculation | Charlson without age_col |
ValueError |
Column 'code' must contain ICD codes as strings | Numeric code column |
AssertionError |
implementation must be one of: … | Unknown implementation (or weights) |
AssertionError |
Implementation 'sokolowski' requires a 'year_col' column | Year-specific implementation (sokolowski, ahrq_icd10) without the year column |
AssertionError |
icd_version must be 'icd10' for HFRS | hfrs with another ICD version |
AssertionError |
Target year must be between 2015 and 2027 | icd_modification_target_year outside the table. The message shows the range of the chosen modification: 2004–2026 for icd10gm, 2015–2027 for icd10cm |
AssertionError |
All values in column 'code' must start with an uppercase letter (A-Z) | ICD modification on codes that are not ICD-10 (e.g. ICD-9 codes with icd_version="icd10") |
ValueError |
Unknown icd_modification: … | icd_modification is not icd10gm or icd10cm |
ValueError |
weights='ahrq' requires icd_version 'icd9' or 'icd10' | weights="ahrq" with icd_version="icd9_10" |
AssertionError |
For icd9_10, … (ICD version) column must be present | icd_version="icd9_10" without icd_version_col |
UserWarning |
Implementation 'deyo' only uses ICD-9. Setting ICD version to 'icd9' | The implementation covers one ICD version only; your icd_version was replaced |
UserWarning |
Implementation 'rcs' requires 'rcs_weights'. Overriding weights=… | weights other than the implementation's own for rcs, uk_shmi, ahrq_icd9, ahrq_icd10 |
UserWarning |
Codes with year(s) [2030] in column 'year' lie outside the transfer table (2015-2027) and are used unchanged | ICD modification for years the table does not cover |
Validation
The scoring is tested against an independent re-implementation in plain Python that reads the same mapping and weight files, for every implementation and weighting scheme and for every category. The test suite requires 100 % coverage and runs on Python 3.10–3.13, including the lowest supported polars version. See Development to run it.