Scope
Compute the 19-condition Charlson Comorbidity Index (CCI) without age points. Handles binary indicators, optional bounds screening, and NA policies.
When to use
- You have binary comorbidity indicators and need the canonical Charlson score (no age points here).
- You want explicit row-retention rules for missing indicators.
Requirements checklist
- Packages: HealthMarkers, dplyr (for display).
- Data columns: binary 0/1 indicators for the 19 conditions.
- Column map: provide all 19 keys -> columns; missing mappings abort.
- Row policy: na_action = keep (default), omit, error; warn/ignore act like keep but warn.
Load packages and example data
Illustrative-only flags below; replace with your real comorbidity indicators.
library(HealthMarkers)
library(dplyr)
sim_path <- system.file("extdata", "simulated_hm_data.rds", package = "HealthMarkers")
sim <- readRDS(sim_path)
sim_small <- dplyr::slice_head(sim, n = 30)
# Illustrative binary flags
set.seed(123)
sim_small <- sim_small %>% mutate(
mi = rbinom(n(), 1, 0.1),
chf = rbinom(n(), 1, 0.1),
pvd = rbinom(n(), 1, 0.1),
stroke = rbinom(n(), 1, 0.1),
dementia = rbinom(n(), 1, 0.05),
copd = rbinom(n(), 1, 0.15),
rheum = rbinom(n(), 1, 0.05),
ulcer = rbinom(n(), 1, 0.05),
mild_liver = rbinom(n(), 1, 0.05),
diabetes = rbinom(n(), 1, 0.2),
diab_comp = rbinom(n(), 1, 0.05),
hemiplegia = rbinom(n(), 1, 0.02),
renal = rbinom(n(), 1, 0.08),
cancer = rbinom(n(), 1, 0.08),
leukemia = rbinom(n(), 1, 0.01),
lymphoma = rbinom(n(), 1, 0.01),
sev_liver = rbinom(n(), 1, 0.02),
metastatic_cancer = rbinom(n(), 1, 0.01),
hiv = rbinom(n(), 1, 0.01)
)Map columns
Provide all 19 keys. Missing mappings error.
col_map <- list(
mi="mi", chf="chf", pvd="pvd", stroke="stroke", dementia="dementia", copd="copd",
rheum="rheum", ulcer="ulcer", mild_liver="mild_liver", diabetes="diabetes",
diab_comp="diab_comp", hemiplegia="hemiplegia", renal="renal", cancer="cancer",
leukemia="leukemia", lymphoma="lymphoma", sev_liver="sev_liver",
metastatic_cancer="metastatic_cancer", hiv="hiv"
)Quick start: compute CCI
Defaults keep rows with missing indicators and return NA scores for them.
cci_out <- charlson_index(
data = sim_small,
col_map = col_map,
na_action = "keep",
verbose = FALSE
)
head(cci_out)
#> # A tibble: 6 × 2
#> id charlson_index
#> <chr> <int>
#> 1 P001 4
#> 2 P002 1
#> 3 P003 0
#> 4 P004 0
#> 5 P005 1
#> 6 P006 1Arguments that matter
- col_map: all 19 keys required; missing or empty entries abort.
- na_action: keep (default), omit (drop rows with missing indicators), error (abort on missing); warn/ignore behave like keep but warn.
- verbose: emit step messages.
Handling missing and non-binary inputs
- Non-numeric inputs are coerced; NA introduced are warned. Non-finite become NA.
- Missing indicators yield NA scores unless na_action = “omit” or “error”.
- Out-of-range (non 0/1) values warn; recode non-binary values to 0/1 before passing.
Compare row policies
demo <- sim_small[1:8, names(col_map)]
demo$renal[3] <- NA
a_keep <- charlson_index(demo, col_map, na_action = "keep")
a_omit <- charlson_index(demo, col_map, na_action = "omit")
list(
keep_rows = nrow(a_keep),
omit_rows = nrow(a_omit),
preview = head(a_keep$charlson_index)
)
#> $keep_rows
#> [1] 8
#>
#> $omit_rows
#> [1] 7
#>
#> $preview
#> [1] 4 1 NA 0 1 1Out-of-bounds indicators
Indicators outside 0-1 will warn. Pre-filter or recode non-binary values before calling.
demo2 <- demo
demo2$mi[5] <- 2 # out of bounds — will warn
# Recode to valid binary before passing if needed
demo2$mi[5] <- as.integer(demo2$mi[5] > 0)
head(charlson_index(demo2, col_map = col_map, na_action = "keep")$charlson_index)
#> [1] 4 1 NA 0 1 1Outputs
- charlson_index integer total
- Rows drop only with na_action = “omit”; na_action = “error” aborts on missing.
Pitfalls and tips
- Indicators must be truly binary; non-binary values warn; recode before passing.
- Provide all 19 mappings; missing keys error.
- Age points are not included here; add separately if needed.
Validation ideas
- Set all indicators to 0: expected score 0.
- Single metastatic_cancer = 1, all else 0: expected score 6.
- diabetes = 1 and diab_comp = 1: expected diabetes contribution = 2 (max rule).
Verbose diagnostics
Set verbose = TRUE to emit three structured messages per
call:
- Preparing inputs — start-of-function signal.
-
Column map — confirms which data column each
comorbidity key resolved to. Example:
charlson_index(): column map: mi -> 'mi', chf -> 'chf', ... -
Results summary — shows how many rows computed
successfully (non-NA) per output column. Example:
charlson_index(): results: charlson_index 30/30, charlson_index_age 30/30, ...
verbose = TRUE emits at the "inform" level;
you also need options(healthmarkers.verbose = "inform")
active:
old_opt <- options(healthmarkers.verbose = "inform")
patient <- tibble::tibble(
mi=0, chf=0, pvd=0, stroke=0, dementia=0, copd=0, rheum=0, ulcer=0,
mild_liver=0, diabetes=1, diab_comp=1, hemiplegia=0, renal=1,
cancer=0, leukemia=0, lymphoma=0, sev_liver=0, metastatic_cancer=0, hiv=0
)
cm_v <- as.list(stats::setNames(names(patient), names(patient)))
charlson_index(patient, col_map = cm_v, verbose = TRUE)
#> charlson_index(): reading input 'patient' — 1 rows × 19 variables
#> charlson_index(): col_map: mi -> 'mi', chf -> 'chf', pvd -> 'pvd', stroke -> 'stroke', dementia -> 'dementia', copd -> 'copd', rheum -> 'rheum', ulcer -> 'ulcer', mild_liver -> 'mild_liver', diabetes -> 'diabetes', diab_comp -> 'diab_comp', hemiplegia -> 'hemiplegia', renal -> 'renal', cancer -> 'cancer', leukemia -> 'leukemia', lymphoma -> 'lymphoma', sev_liver -> 'sev_liver', metastatic_cancer -> 'metastatic_cancer', hiv -> 'hiv'
#> charlson_index(): computing markers:
#> charlson_index [mi, chf, pvd, stroke, dementia, copd, rheum, ulcer, mild_liver, diabetes, diab_comp, hemiplegia, renal, cancer, leukemia, lymphoma, sev_liver, metastatic_cancer, hiv]
#> charlson_index(): results: charlson_index 1/1
#> # A tibble: 1 × 1
#> charlson_index
#> <int>
#> 1 4
options(old_opt)Reset with options(healthmarkers.verbose = NULL) or
"none".