comorbidity
Data ManagementCharlson and Elixhauser comorbidity scores from ICD-10 diagnosis fields
Version 1.0.0
comorbidity scans wide-format ICD-10 diagnosis fields and creates patient-level Charlson, Elixhauser, or custom weighted scores. It is for analysts who need to turn one or more diagnosis variables per encounter into condition indicators and a reproducible comorbidity score.
Quick Start
After installation, scan diagnosis fields and collapse to one row per patient:
clear
input long pid str6 dx1 str6 dx2
1 "I21" "I50"
1 "E119" ""
2 "C780" ""
end
comorbidity dx1 dx2, id(pid) charlson(original)
list pid charlson mi chf dm_uncomp metastatic
The default output is collapsed by id(). In this example, patient 1 has score 3 and patient 2 has score 6.
Requirements
- Stata 16 or later
- The
codescandependency - One or more wide-format diagnosis variables and an identifier for the patient or analytic unit
Installation
Install the scanner dependency first:
net install codescan, from("https://raw.githubusercontent.com/tpcopeland/Stata-Tools/main/codescan") replace
Then install comorbidity:
capture ado uninstall comorbidity
net install comorbidity, from("https://raw.githubusercontent.com/tpcopeland/Stata-Tools/main/comorbidity") replace
Commands
| Command | Description |
|---|---|
comorbidity |
Scan wide-format ICD-10 fields, apply optional hierarchy rules, and compute a Charlson, Elixhauser, or custom weighted score |
How It Works
comorbidity passes the diagnosis variables to codescan with a built-in or user-supplied code dictionary, then applies the selected weights to the resulting binary condition indicators.
charlson(original)andcharlson(quan2011)use the Quan et al. (2005) Charlson ICD-10 definitions with the corresponding weight scheme.elixhauser(vanwalraven)uses the Quan et al. (2005) Elixhauser ICD-10 definitions and van Walraven weights.custom(filename)reads condition names, ICD-10 patterns, and weights from a.csvor.dtacode file.collapseproduces one row perid()and is the default when neithercollapsenormergeis specified;mergereturns patient-level indicators and the score on the encounter rows.- Built-in Charlson and Elixhauser indexes use hierarchy rules by default. Use
nohierarchywhen you need the unadjusted indicators; custom indexes do not apply a built-in hierarchy.
Worked Examples
1. Charlson scores and score bands
band adds patient-level counts and percentages for negative scores, 0, greater than 0 to less than 3, 3 to less than 5, and 5 or greater to r(bands). These bands are exhaustive for integer and fractional scores.
clear
input long pid str6 dx1 str6 dx2
1 "I21" "I50"
1 "E119" ""
2 "C780" ""
3 "" ""
end
comorbidity dx1 dx2, id(pid) charlson(original) band
list pid charlson mi chf dm_uncomp metastatic, noobs
matrix list r(bands)
2. Merge a generated score back to encounter rows
Use generate() to prefix the component indicators and score variable. replace permits the example to overwrite the placeholder score variable.
clear
input long pid str6 dx1 str6 dx2
1 "I21" "I50"
1 "E119" ""
2 "C780" ""
end
gen double cmb_score = -99
comorbidity dx1 dx2, id(pid) charlson(quan2011) merge generate(cmb_) replace
list pid dx1 dx2 cmb_score cmb_mi cmb_chf cmb_dm_uncomp cmb_metastatic, noobs
3. Elixhauser van Walraven scoring
The van Walraven score can be negative because its published weight vector includes negative weights.
clear
input long pid str6 dx1 str6 dx2 str6 dx3
1 "I50" "C780" "F11"
2 "E66" "F32" ""
3 "I10" "I11" "E112"
end
comorbidity dx1 dx2 dx3, id(pid) elixhauser(vanwalraven) generate(elx_) replace band
list pid elx_score elx_chf elx_metastatic elx_drug elx_obesity elx_depression, noobs
matrix list r(bands)
4. Restrict matching to a date window
Supply encounter and reference dates with date() and refdate(), then set the lookback and lookforward windows in days.
clear
input long pid str6 dx1 int dxdate int refdate
1 "I50" 21910 21915
1 "I21" 21885 21915
2 "I50" 21550 21915
end
format dxdate refdate %td
comorbidity dx1, id(pid) charlson(original) date(dxdate) refdate(refdate) lookback(30) lookforward(10) inclusive
list pid charlson mi chf, noobs
5. Use a custom weighted code file
The custom file must contain name, pattern, and weight columns. Each detected condition must have exactly one matching weight.
clear
input long pid str6 dx1 str6 dx2
1 "I21" "I50"
2 "E119" ""
end
tempfile custom_codes
preserve
clear
input str12 name str20 pattern double weight
"mi" "I21|I22" 10
"chf" "I50" 2
"dm" "E11" 4
end
save "`custom_codes'.dta", replace
restore
comorbidity dx1 dx2, id(pid) custom("`custom_codes'.dta") replace
list pid custom mi chf dm, noobs
Demo
The repository demo exercises the built-in indexes, merge and collapse output, generated names, date windows, hierarchy control, custom weights, and verbose scanning. From the repository root, run:
stata-mp -b do comorbidity/demo/demo_comorbidity.do
The checked-in console transcript is demo/console_output.md.
Command Reference
comorbidity varlist [if] [in], id(varname) charlson(scheme) [options]
comorbidity varlist [if] [in], id(varname) elixhauser(scheme) [options]
comorbidity varlist [if] [in], id(varname) custom(filename) [options]
Exactly one of charlson(), elixhauser(), or custom() is required. collapse and merge are mutually exclusive, and collapse is selected automatically when neither is specified.
Key Options
| Option | Use |
|---|---|
id(varname) |
Required patient or analytic-unit identifier |
charlson(scheme) |
Choose original or quan2011 Charlson weights |
elixhauser(scheme) |
Choose implemented vanwalraven weights; AHRQ scheme names are reserved and exit with error code r(198) in this build |
custom(filename) |
Read a .csv or .dta code file containing name, pattern, and weight |
collapse |
Return one row per id(); default output shape |
merge |
Merge patient-level indicators and the score back to encounter rows |
date(varname) |
Encounter date variable passed to codescan |
refdate(varname) |
Reference date variable passed to codescan |
lookback(#) |
Pass a nonnegative lookback window in days; default -1 passes no lower bound |
lookforward(#) |
Pass a nonnegative lookforward window in days; default -1 passes no upper bound |
inclusive |
Include the reference date in the date window |
generate(prefix) |
Prefix condition indicators and name the score prefixscore |
replace |
Overwrite existing nonstructural condition and score variables; identifiers, diagnosis fields, and date inputs remain protected |
nohierarchy |
Skip built-in hierarchy rules for a Charlson or Elixhauser run |
band |
Return exhaustive patient-level score-band counts and percentages in r(bands) |
noisily |
Pass verbose progress output through to codescan |
Stored Results
After a successful run, comorbidity stores:
| Result | Type | Meaning |
|---|---|---|
r(index) |
Local macro | Resolved index: charlson, elixhauser, or custom |
r(scheme) |
Local macro | Resolved weighting scheme |
r(scorevar) |
Local macro | Generated score variable name |
r(conditions) |
Local macro | Condition indicator variables in score order |
r(N) |
Scalar | Patient-level count reported by codescan |
r(hierarchy) |
Scalar | 1 when a built-in hierarchy was applied, otherwise 0 |
r(weights) |
Matrix | Per-condition weights in score order |
r(summary) |
Matrix | Post-hierarchy patient counts, prevalence, missing binary-mode hit totals, and positive units |
r(bands) |
Matrix | Patient-level score-band counts and percentages when band is specified |
Assumptions and Limits
- The input diagnosis fields are wide-format variables containing ICD-10 codes that can be matched by
codescan. - Charlson hierarchy rules supersede uncomplicated diabetes with complicated diabetes, mild liver disease with severe liver disease, and any malignancy with metastatic cancer.
- Elixhauser hierarchy rules supersede uncomplicated hypertension with complicated hypertension, solid tumor without metastasis with metastatic cancer, and uncomplicated diabetes with complicated diabetes.
elixhauser(ahrq_mortality)andelixhauser(ahrq_readmission)are reserved but not implemented in this development build and exit with error coder(198).- Custom code files are limited to
.csvand.dtaextensions and must provide one nonmissing numeric weight per unique condition name. The schema and output names are checked before diagnosis scanning begins. replacecannot overwriteid(), diagnosis variables,date(), orrefdate()through either the score name or a custom condition name.
References
- Charlson ME, Pompei P, Ales KL, MacKenzie CR. A new method of classifying prognostic comorbidity in longitudinal studies: development and validation. J Chronic Dis. 1987;40(5):373–383. doi:10.1016/0021-9681(87)90171-8
- Quan H, Sundararajan V, Halfon P, et al. Coding algorithms for defining comorbidities in ICD-9-CM and ICD-10 administrative data. Med Care. 2005;43(11):1130–1139. doi:10.1097/01.mlr.0000182534.19832.83
- Quan H, Li B, Couris CM, et al. Updating and validating the Charlson comorbidity index and score for risk adjustment in hospital discharge abstracts using data from 6 countries. Am J Epidemiol. 2011;173(6):676–682. doi:10.1093/aje/kwq433
- van Walraven C, Austin PC, Jennings A, Quan H, Forster AJ. A modification of the Elixhauser comorbidity measures into a point system for hospital death using administrative data. Med Care. 2009;47(6):626–633. doi:10.1097/MLR.0b013e31819432e5
QA
QA suites and how to run them are documented in qa/README.md.
Version History
- 1.0.0: Initial development build with Charlson original, Charlson Quan 2011, Elixhauser van Walraven, custom weighted code files, and hierarchy handling
Author
Timothy P Copeland, Karolinska Institutet
License
MIT License