Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M3 Multimorbidity Index implemented for ICD-10-AM. #59

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ Authors@R:
family = "Teo",
role = "ctb",
email = "ed_teo8@yahoo.com.sg",
comment = c(ORCID = "0000-0003-3936-4082")))
comment = c(ORCID = "0000-0003-3936-4082")),
person(given = "Matthew",
family = "Moore",
role = "ctb",
email = "matthew.moore@auckland.ac.nz",
comment = c(ORCID = "0000-0003-0730-8027")))
Maintainer: Alessandro Gasparini <alessandro.gasparini@ki.se>
URL: https://ellessenne.github.io/comorbidity/, https://github.com/ellessenne/comorbidity/
BugReports: https://github.com/ellessenne/comorbidity/issues
Expand Down
18 changes: 18 additions & 0 deletions R/assign0.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@
# "Solid tumour" (`solidtum`) and "Metastatic cancer" (`metacanc`)
x[metacanc == 1, solidtum := 0]
# x$solidtum[x$metacanc == 1] <- 0
} else if (grepl("m3", map)) {
# Diabetes complicated: add if has diabetes uncomplicated + one or more complication codes...
x[diabunc == 1 & flag_comp_diab == 1, diabc := 1]
# Set Diabetes uncomplicated to zero if diabetes complicated recorded or complications found
x[diabc == 1 | flag_comp_diab == 1, diabunc := 0]
# Exclusions for osteoporosis and hypertension.
x[flag_exc_osteo == 1, osteounc := 0]
x[flag_exc_hyp == 1, hypunc := 0]
# Exclude other cancers if metastatic cancer found.
# for (canc_col_name in names(x)[names(x) %like% '^canc']) {
data.table::set(
x,
i = which(x[, metacanc == 1]),
j = names(x)[data.table::like(names(x), '^canc')],
value = 0
)
# }

}
return(x)
}
77 changes: 74 additions & 3 deletions R/comorbidity.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#' @title Comorbidity mapping.
#'
#' @description Maps comorbidity conditions using algorithms from the Charlson and the Elixhauser comorbidity scores.
#' @description Maps comorbidity conditions using algorithms from the Charlson, Elixhauser, and M3 Multimorbidity Index comorbidity scores.
#'
#' @param x A tidy `data.frame` (or a `data.table`; `tibble`s are supported too) with one column containing an individual ID and a column containing all diagnostic codes.
#' Extra columns other than ID and codes are discarded.
Expand All @@ -9,7 +9,7 @@
#' @param code Column of `x` containing diagnostic codes.
#' Codes must be in upper case with no punctuation in order to be properly recognised.
#' @param map The mapping algorithm to be used (values are case-insensitive).
#' Possible values are the Charlson score with either ICD-10 or ICD-9-CM codes (`charlson_icd10_quan`, `charlson_icd9_quan`) and the Elixhauser score, again using either ICD-10 or ICD-9-CM (`elixhauser_icd10_quan`, `elixhauser_icd9_quan`).
#' Possible values are the Charlson score with either ICD-10 or ICD-9-CM codes (`charlson_icd10_quan`, `charlson_icd9_quan`), the Elixhauser score, again using either ICD-10 or ICD-9-CM (`elixhauser_icd10_quan`, `elixhauser_icd9_quan`), and the M3 Multimorbidity Index (`m3_icd10_am`) .
#' These mapping are based on the paper by Quan et al. (2011).
#' It is also possible to obtain a Swedish (`charlson_icd10_se`) or Australian (`charlson_icd10_am`) modification of the Charlson score using ICD-10 codes.
#' @param assign0 Apply a hierarchy of comorbidities: should a comorbidity be present in a patient with different degrees of severity, then the milder form will be assigned a value of 0.
Expand All @@ -21,6 +21,9 @@
#' * "Hypertension, uncomplicated" (`hypunc`) and "Hypertension, complicated" (`hypc`) for the Elixhauser score;
#' * "Diabetes, uncomplicated" (`diabunc`) and "Diabetes, complicated" (`diabc`) for the Elixhauser score;
#' * "Solid tumour" (`solidtum`) and "Metastatic cancer" (`metacanc`) for the Elixhauser score.
#' * "Diabetes" (`diab`) and "Diabetes with complications" (`diabwc`) for the M3 score;
#' * "Osteoporosis, uncomplicated" (`ostunc`) and "Hypertension, uncomplicated" (`hypunc`) for the M3 score;
#' * All cancers (`canc.+`) for the M3 score;
#'
#' @param labelled Attach labels to each comorbidity, compatible with the RStudio viewer via the [utils::View()] function.
#' Defaults to `TRUE`.
Expand Down Expand Up @@ -51,7 +54,7 @@
#' * `aids`, for AIDS/HIV.
#' Please note that we combine "chronic obstructive pulmonary disease" and "chronic other pulmonary disease" for the Swedish version of the Charlson index, for comparability (and compatibility) with other definitions/implementations.
#'
#' Conversely, for the Elixhauser score the dataset contains the following variables:
#' For the Elixhauser score the dataset contains the following variables:
#' * The `id` variable as defined by the user;
#' * `chf`, for congestive heart failure;
#' * `carit`, for cardiac arrhythmias;
Expand Down Expand Up @@ -84,18 +87,86 @@
#' * `drug`, for drug abuse;
#' * `psycho`, for psychoses;
#' * `depre`, for depression;
#'
#' * The `id` variable as defined by the user;
#' * `aids`, for AIDS/HIV;
#' * `alcohol`, for Alcohol abuse;
#' * `dane`, for Anemia deficiency;
#' * `anxbd`, for Anxiety and Behavioural disorders;
#' * `aneur`, for Aortic and other aneurysms;
#' * `bone`, for Bone disorders;
#' * `bdi`, for Bowel disease inflammatory;
#' * `cancbreast`, for Breast cancer;
#' * `carit`, for Cardiac arrhythmia;
#' * `valv`, for Cardiac valve;
#' * `cevd`, for Cerebrovascular disease;
#' * `copd`, for Chronic pulmonary;
#' * `rend`, for Chronic renal;
#' * `blood`, for Coagulopathy and other blood disorder;
#' * `canccolrec`, for Colorectal cancer;
#' * `chf`, for Congestive heart failure;
#' * `conntiss`, for Connective tissue disease;
#' * `dementia`, for Dementia;
#' * `diabc`, for Diabetes (complicated);
#' * `diabunc`, for Diabetes (uncomplicated);
#' * `drug`, for Drug abuse;
#' * `endo`, for Endocrine disorder;
#' * `epi`, for Epilepsy;
#' * `ceye`, for Eye problem long term;
#' * `cancgyn`, for Gynaecological cancers;
#' * `cvhep`, for Hepatitis, chronic viral;
#' * `hypunc`, for Hypertension (uncomplicated);
#' * `immsys`, for Immune system disorder;
#' * `inear`, for Inner ear disorder;
#' * `jsd`, for Joint or spinal disorder;
#' * `msld`, for Liver disease (moderate or severe);
#' * `canclung`, for Lung cancer;
#' * `canclymphleuk`, for Lymphomas and leukaemias;
#' * `mpd`, for Major psychiatric disorder;
#' * `cancmela`, for Malignant melanoma;
#' * `maln`, for Malnutrition and other nutritional disorders;
#' * `bd`, for Mental and behavioural disorders due to brain damage;
#' * `mentret`, for Mental retardation;
#' * `metab`, for Metabolic disorder;
#' * `metacanc`, for Metastatic cancer;
#' * `mpnd`, for Muscular peripheral nerve disorder;
#' * `ami`, for Myocardial infarction;
#' * `obes`, for Obesity;
#' * `osteounc`, for Osteoporosis (uncomplicated);
#' * `cancoth`, for Other cancers;
#' * `ond`, for Other neurologic disorders (excluding epilepsy);
#' * `para`, for Paralysis;
#' * `pud`, for Peptic ulcer disease;
#' * `pvd`, for Peripheral vascular disease;
#' * `cancprost`, for Prostate cancer;
#' * `pcd`, for Pulmonary circulation disorders;
#' * `sleep`, for Sleep disorder;
#' * `cancuppergi`, for Upper gastrointestinal cancer;
#' * `utc`, for Urinary tract problem (chronic);
#' * `ven`, for Venous insufficiency;
#' * `ang`, for Angina;
#' * `cdnos`, for Cardiac disease (other);
#' * `cinfnos`, for Infection chronic NOS;
#' * `intest`, for Intestinal disorder;
#' * `panc`, for Pancreatitis;
#' * `tub`, for Tuberculosis;
#' * `flag_comp_diab`, for flagging for diabetes complications;
#' * `flag_exc_osteo`, for flagging for osteoporosis exclusions;
#' * `flag_exc_hyp`, for flagging for hypertension exclusions;
Comment on lines +153 to +155
Copy link
Owner

@ellessenne ellessenne Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, these are flags to set these comorbidities to zero if any of these codes are found. Is that right?

If so, do you think it would be a good idea to drop them before returning the dataset with comorbidities?

In addition to that, I would suggest re-arranging these to be in the same order of Supplementary Table 5 in the Stanley and Sarfati paper.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Alessandro. I do think that would result in a cleaner user experience, the potential issues that I saw were:

  • That is not implemented (or necessary) for the other scales, so wasn't sure if that's a direction you wanted to go.
  • My understanding would be that it is implemented in .assign0(), but given that is called in both comorbidity() and score(), could removing columns at one stage or the other result in an error state (particularly when multiplying by weights) that requires M3-specific code in those functions?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates and clarifications.

I was exactly thinking about including this in assign0(), but then realised (as you point out here) that such columns would be needed by the score() function.

I need to think a bit about how to implement this effectively within the current infrastructure. I will leave this hanging for now, but I'll get back to you - hope that's okay!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, will wait to hear from you.

#'
#' Labels are presented to the user when using the RStudio viewer (e.g. via the [utils::View()] function) for convenience.
#'
#' @details
#' The ICD-10 and ICD-9-CM coding for the Charlson and Elixhauser scores is based on work by Quan _et al_. (2005).
#' The ICD-10-AM coding for the M3 Multimorbidity Index is based on work by Stanley and Sarfati (2017).
#' ICD-10 and ICD-9 codes must be in upper case and with alphanumeric characters only in order to be properly recognised; set `tidy.codes = TRUE` to properly tidy the codes automatically.
#' A message is printed to the R console when non-alphanumeric characters are found.
#'
#' @references Quan H, Sundararajan V, Halfon P, Fong A, Burnand B, Luthi JC, et al. _Coding algorithms for defining comorbidities in ICD-9-CM and ICD-10 administrative data_. Medical Care 2005; 43(11):1130-1139.
#' @references Charlson ME, Pompei P, Ales KL, et al. _A new method of classifying prognostic comorbidity in longitudinal studies: development and validation_. Journal of Chronic Diseases 1987; 40:373-383.
#' @references Ludvigsson JF, Appelros P, Askling J et al. _Adaptation of the Charlson Comorbidity Index for register-based research in Sweden_. Clinical Epidemiology 2021; 13:21-41.
#' @references Sundararajan V, Henderson T, Perry C, Muggivan A, Quan H, Ghali WA. _New ICD-10 version of the Charlson comorbidity index predicted in-hospital mortality_. Journal of Clinical Epidemiology 2004; 57(12):1288-1294.
#' @references Stanley J, Sarfati D. (2017) _The new measuring multimorbidity index predicted mortality better than Charlson and Elixhauser indices among the general population_. Journal of Clinical Epidemiology 2017;92:99-110. DOI: 10.1016/j.jclinepi.2017.08.005
#' @examples
#' set.seed(1)
#' x <- data.frame(
Expand Down
4 changes: 3 additions & 1 deletion R/labelled.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
.labelled <- function(x, map) {
attr(x, "variable.labels") <- if (grepl("^charlson_", map)) {
c("ID", "Myocardial infarction", "Congestive heart failure", "Peripheral vascular disease", "Cerebrovascular disease", "Dementia", "Chronic pulmonary disease", "Rheumatoid disease", "Peptic ulcer disease", "Mild liver disease", "Diabetes without chronic complications", "Diabetes with chronic complications", "Hemiplegia or paraplegia", "Renal disease", "Cancer (any malignancy)", "Moderate or severe liver disease", "Metastatic solid tumour", "AIDS/HIV")
} else if (grepl("^m3_", map)) {
labs = c( "ID", "AIDS/HIV", "Alcohol abuse", "Anemia deficiency", "Anxiety and Behavioural disorders", "Aortic and other aneurysms", "Bone disorders", "Bowel disease inflammatory", "Breast cancer", "Cardiac arrhythmia", "Cardiac valve", "Cerebrovascular disease", "Chronic pulmonary", "Chronic renal", "Coagulopathy and other blood disorders", "Colorectal cancer", "Congestive heart failure", "Connective tissue disease", "Dementia", "Diabetes (complicated)", "Diabetes (uncomplicated)", "Drug abuse", "Endocrine disorder", "Epilepsy", "Eye problem long term", "Gynaecological cancers", "Hepatitis, chronic viral", "Hypertension (uncomplicated)", "Immune system disorder", "Inner ear disorder", "Joint or spinal disorder", "Liver disease (moderate or severe)", "Lung cancer", "Lymphomas and leukaemias", "Major psychiatric disorder", "Malignant melanoma", "Malnutrition and other nutritional disorders", "Mental and behavioural disorders due to brain damage", "Mental retardation", "Metabolic disorder", "Metastatic cancer", "Muscular peripheral nerve disorders", "Myocardial infarction", "Obesity", "Osteoporosis (uncomplicated)", "Other cancers", "Other neurologic disorders (excluding epilepsy)", "Paralysis", "Peptic ulcer disease", "Peripheral vascular disease", "Prostate cancer", "Pulmonary circulation disorders", "Sleep disorder", "Upper gastrointestinal cancer", "Urinary tract problem (chronic)", "Venous insufficiency", "Angina", "Cardiac disease (other)", "Infection chronic NOS", "Intestinal disorder", "Pancreatitis", "Tuberculosis", "Flag for diabetes complications", "Flag for osteoporosis exclusions", "Flag for hypertension exclusions" )
} else {
c("ID", "Congestive heart failure", "Cardiac arrhythmias", "Valvular disease", "Pulmonary circulation disorders", "Peripheral vascular disorders", "Hypertension, uncomplicated", "Hypertension, complicated", "Paralysis", "Other neurological disorders", "Chronic pulmonary disease", "Diabetes, uncomplicated", "Diabetes, complicated", "Hypothyroidism", "Renal failure", "Liver disease", "Peptic ulcer disease excluding bleeding", "AIDS/HIV", "Lymphoma", "Metastatic cancer", "Solid tumour without metastasis", "Rheumatoid artritis/collaged vascular disease", "Coagulopathy", "Obesity", "Weight loss", "Fluid and electrolyte disorders", "Blood loss anaemia", "Deficiency anaemia", "Alcohol abuse", "Drug abuse", "Psychoses", "Depression")
}
return(x)
}
}
8 changes: 7 additions & 1 deletion R/score.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#' @title Compute (weighted) comorbidity scores
#'
#' @param x An object of class `comorbidty` returned by a call to the [comorbidity()] function.
#' @param x An object of class `comorbidity` returned by a call to the [comorbidity()] function.
#'
#' @param weights The weighting system to be used.
#' This will depend on the mapping algorithm.
Expand All @@ -10,6 +10,8 @@
#' Possible values for the Elixhauser score are:
#' * `vw`, for the weights by van Walraven et al. (2009);
#' * `swiss`, for the Swiss Elixhauser weights by Sharma et al. (2021).
#' Possible values for the M3 score are:
#' * `m3`, for the weights by Stanley and Sarfati (2017);
#'
#' Defaults to `NULL`, in which case an unweighted score will be used.
#'
Expand All @@ -22,11 +24,15 @@
#' * "Hypertension, uncomplicated" (`hypunc`) and "Hypertension, complicated" (`hypc`) for the Elixhauser score;
#' * "Diabetes, uncomplicated" (`diabunc`) and "Diabetes, complicated" (`diabc`) for the Elixhauser score;
#' * "Solid tumour" (`solidtum`) and "Metastatic cancer" (`metacanc`) for the Elixhauser score.
#' * "Diabetes" (`diab`) and "Diabetes with complications" (`diabwc`) for the M3 score;
#' * "Osteoporosis, uncomplicated" (`ostunc`) and "Hypertension, uncomplicated" (`hypunc`) for the M3 score;
#' * All cancers (`canc.+`) for the M3 score;
#'
#' @references Charlson ME, Pompei P, Ales KL, et al. _A new method of classifying prognostic comorbidity in longitudinal studies: development and validation_. Journal of Chronic Diseases 1987; 40:373-383.
#' @references 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_. American Journal of Epidemiology 2011; 173(6):676-682.
#' @references van Walraven C, Austin PC, Jennings A, Quan H and Forster AJ. _A modification of the Elixhauser comorbidity measures into a point system for hospital death using administrative data_. Medical Care 2009; 47(6):626-633.
#' @references Sharma N, Schwendimann R, Endrich O, et al. _Comparing Charlson and Elixhauser comorbidity indices with different weightings to predict in-hospital mortality: an analysis of national inpatient data_. BMC Health Services Research 2021; 21(13).
#' @references Stanley J, Sarfati D. (2017) _The new measuring multimorbidity index predicted mortality better than Charlson and Elixhauser indices among the general population_. Journal of Clinical Epidemiology 2017;92:99-110. DOI: 10.1016/j.jclinepi.2017.08.005
#'
#' @return A numeric vector with the (weighted) comorbidity score for each subject from the input dataset.
#'
Expand Down
Binary file modified R/sysdata.rda
Binary file not shown.
Loading