Skip to contents

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               1

Arguments 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  1

Out-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  1

Outputs

  • 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:

  1. Preparing inputs — start-of-function signal.
  2. Column map — confirms which data column each comorbidity key resolved to. Example: charlson_index(): column map: mi -> 'mi', chf -> 'chf', ...
  3. 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".

See also

  • metss and metabolic_risk_features for metabolic burden scoring.
  • health_summary() to combine multiple indices.