Authors: Sebastian Gibb [aut, cre] (https://orcid.org/0000-0001-7406-4443)
Last modified: 2022-12-05 12:37:50
Compiled: Mon Dec 5 12:39:17 2022

The ameld Package

The ameld R package provides a dataset, eldd, of patients evaluated for liver transplantation at the University Hospital of Leipzig from November 2012 to June 2015. eldr contains the reference limits for the laboratory measurements used in eldd.

Access the Data

The datasets could be loaded as follows:

library("ameld")
data(eldd)
data(eldr)

colnames(eldd)
##  [1] "Age"         "Sex"         "DaysAtRisk"  "Deceased"    "LTx"        
##  [6] "Cirrhosis"   "ALF"         "Ethyltoxic"  "HBV"         "HCV"        
## [11] "AIH"         "PBC"         "PSC"         "NASH"        "Cryptogenic"
## [16] "Dialysis"    "GIB"         "HCC"         "SBP"         "ALAT_S"     
## [21] "ALB_S"       "AP_S"        "ASAT_S"      "B_MPV_E"     "B_PLT_E"    
## [26] "B_WBC_E"     "BILI_S"      "BILID_S"     "CA_S"        "CHE_S"      
## [31] "CHOLG_S"     "CL_S"        "CRE_S"       "CRP_S"       "CYSC_S"     
## [36] "GGT_S"       "IL6_S"       "INR_C"       "NA_S"        "P_S"        
## [41] "PALB_S"      "PROT_S"      "PTH_S"       "VDT_OH_S"
knitr::kable(head(eldd[, 1:10]))
Age Sex DaysAtRisk Deceased LTx Cirrhosis ALF Ethyltoxic HBV HCV
68 male 200 0 0 1 0 1 1 0
64 male 3 1 0 1 0 1 0 0
67 female 208 0 0 1 0 1 0 0
32 female 17 1 0 0 1 0 0 0
64 female 189 0 0 1 0 1 0 0
79 male 674 0 0 1 0 1 0 0
knitr::kable(head(eldr))
Code Unit LongDescription ShortDescription LowerLimit UpperLimit AgeDays Sex
ALAT_S µkat/l alanine aminotransferase ALAT 0.17 0.85 6574 male
ALAT_S µkat/l alanine aminotransferase ALAT 0.17 0.58 6574 female
ALB_S g/l albumin Alb 35.00 52.00 6574 both
AP_S µkat/l alkaline phosphatase AP 0.67 2.15 6574 male
AP_S µkat/l alkaline phosphatase AP 0.58 1.74 6574 female
ASAT_S µkat/l aspartate aminotransferase ASAT 0.17 0.85 6574 male

Survival Estimates

The ameld package provides a plot_surv function that is similar to survival::plot.survfit() but uses different defaults:

library("survival")

srv <- Surv(eldd$DaysAtRisk, eldd$Deceased)

srvfit <- survfit(srv ~ 1)

plot_surv(
    srvfit,
    main = "Kaplan-Meier Survival Estimate"
)

plot_surv(
    srvfit,
    cumhaz = TRUE,
    main = "Cumulative Hazard"
)

A more complex example of the survival plot with risk tables could be generated by combining plot_surv and plot_table:

## timepoints of interest
times <- c(0, 30, 90)

## calculate risk tables
sm <- summary(srvfit, times = times)
nrisk <- as.matrix(sm$n.risk)
ncumevents <- as.matrix(cumsum(sm$n.event))
rownames(nrisk) <- rownames(ncumevents) <- times

## keep old graphic parameters and restore them afterwards
old.par <- par(no.readonly = TRUE)

layout(matrix(1:3, nrow = 3), height = c(5, 1, 1))
par(cex.main = 2)
plot_surv(
    srvfit,
    main = "Kaplan-Meier Survival Estimate to day 90",
    times = times,
    xmax = 90
)
par(mar = c(5.1, 4.1, 1.1, 2.1))
plot_table(
    nrisk, at = times, main = "Number at risk",
    xaxis = FALSE, cex.text = 1.5, ylabels = FALSE
)
par(mar = c(5.1, 4.1, 1.1, 2.1))
plot_table(
    ncumevents, at = times, main = "Cumulative number of events",
    xaxis = FALSE, cex.text = 1.5, ylabels = FALSE
)

par(old.par)

Z(log) Transformation

The \(z(log)\)-transformation was suggested in Hoffmann et al. (2017). It is similar to common \(z\)-transformation but standardizes laboratory measurements by their respective reference or normal values. An R implementation is provided by the zlog package (Gibb 2021).

library("zlog")

## transform reference data.frame for zlog
r <- eldr[c("Code", "AgeDays", "Sex", "LowerLimit", "UpperLimit")]
names(r) <- c("param", "age", "sex", "lower", "upper")
r$age <- r$age / 365.25
r <- set_missing_limits(r)

## we just want to standardize laboratory values
cn <- colnames(eldd)
cnlabs <- cn[grepl("_[SCEFQ1]$", cn)]
zeldd <- eldd
zeldd[c("Age", "Sex", cnlabs)] <- zlog_df(eldd[, c("Age", "Sex", cnlabs)], r)

We could use the (mean) \(z(log)\) values to get a first impression of the influence of these values on survival/non-survival:

## divide data.frame by dead/alive
s <- split(zeldd[cnlabs], zeldd$Deceased)
names(s) <- c("survived", "dead")

## calculate mean standardized lab values
s <- lapply(s, colMeans, na.rm = TRUE)
o <- order(s$dead)

## comparison plot
col <- palette.colors(2)

## keep old graphic parameters and restore them afterwards
old.par <- par(no.readonly = TRUE)

par(mar = c(7.1, 4.1, 4.1, 2.1))

plot(
    s$dead[o], type = "b", pch = 20, lwd = 2, col = col[1],
    axes = FALSE, ann = FALSE
)
lines(s$survived[o], type = "b", pch = 20, lwd = 2, col = col[2])
legend(
    "bottomright",
    legend = c("dead", "survived"),
    col = col, lwd = 2, pch = 20, bty = "n"
)
title(
    main = "Mortality Status vs Mean Standardized Laboratory Values", adj = 0
)
title(xlab = "Laboratory Measurements", adj = 1L, line = 5)
title(ylab = "Mean Standardized Values", adj = 1L)
r <- range(unlist(s))
axis(
    2, at = seq(from = floor(r[1]), to = ceiling(r[2])),
    lwd.ticks = 0, col = "#808080"
)
axis(
    1, at = seq_along(o), labels = names(s$dead[o]), las = 2,
    lwd.ticks = 0L, col = "#808080"
)

par(old.par)

Observed vs Expected Mortality

We divide our cohort into 5 MELD-score risk categories as described in Wiesner et al. (2003). Our observed 90 day mortality is higher than the predicted one, except in the lowest category.

eldd$MELD <- meld(
    creatinine = as_metric(eldd$CRE_S, "creatinine"),
    bilirubin = as_metric(eldd$BILI_S, "bilirubin"),
    inr = eldd$INR_C,
    dialysis = eldd$Dialysis,
    cause = "other"
)

# Mortality rates and categories as reported in Wiesner et al. 2003
mr <- c(1.9, 6.0, 19.6, 52.6, 71.3) / 100

mcat <- cut(
    eldd$MELD,
    breaks = c(-Inf, seq(10, 40, by=10), Inf),
    labels = c(
        paste0("[", floor(min(eldd$MELD, na.rm = TRUE)), ",9]"),
        "[10,20)", "[20,30)", "[30,40)",
        paste0( "[40,", ceiling(max(eldd$MELD, na.rm = TRUE)), ")")
    ),
    right = FALSE
)

tbl <- observed_vs_expected_mortality(srv, time = 90, f = mcat, expected = mr)
tbl[c("ObservedMortality", "ExpectedMortality")] <-
    tbl[c("ObservedMortality", "ExpectedMortality")] * 100

knitr::kable(
    tbl,
    col.names =
        c(
            "Observed deaths (n)",
            "Expected deaths (n)",
            "Standardized mortality ratio (SMR)",
            "Observed mortality (%)",
            "Expected mortality (%)"
        ),
    caption = paste0(
        "Observed vs MELD-expected 90 day mortality. ",
        "MELD mortality values are taken from @wiesner2003. ",
        "All patients censored before day 90 are ignored for ",
        " the calculation of the MELD-expected deaths. ",
        "SMR, Standardized mortality ratio = observed deaths/expected deaths."
    ),
    digits = 1
)
Observed vs MELD-expected 90 day mortality. MELD mortality values are taken from Wiesner et al. (2003). All patients censored before day 90 are ignored for the calculation of the MELD-expected deaths. SMR, Standardized mortality ratio = observed deaths/expected deaths.
Observed deaths (n) Expected deaths (n) Standardized mortality ratio (SMR) Observed mortality (%) Expected mortality (%)
[6,9] 1 4.0 0.3 0.5 1.9
[10,20) 21 13.0 1.6 8.9 6.0
[20,30) 34 11.6 2.9 51.0 19.6
[30,40) 18 10.0 1.8 92.8 52.6
[40,52) 6 4.3 1.4 100.0 71.3

Acknowledgment

This work is part of the AMPEL (Analysis and Reporting System for the Improvement of Patient Safety through Real-Time Integration of Laboratory Findings) project.

This measure is co-funded with tax revenues based on the budget adopted by the members of the Saxon State Parliament.

Session Information

## R version 4.2.2 (2022-10-31)
## Platform: x86_64-apple-darwin17.0 (64-bit)
## Running under: macOS Big Sur ... 10.16
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRlapack.dylib
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] zlog_1.0.1.9000 ameld_0.0.31    survival_3.4-0  glmnet_4.1-6   
## [5] Matrix_1.5-1   
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.9        highr_0.9         bslib_0.4.1       compiler_4.2.2   
##  [5] jquerylib_0.1.4   iterators_1.0.14  tools_4.2.2       digest_0.6.30    
##  [9] jsonlite_1.8.3    evaluate_0.18     memoise_2.0.1     lifecycle_1.0.3  
## [13] lattice_0.20-45   rlang_1.0.6       foreach_1.5.2     cli_3.4.1        
## [17] yaml_2.3.6        pkgdown_2.0.6     xfun_0.35         fastmap_1.1.0    
## [21] stringr_1.5.0     knitr_1.41        desc_1.4.2        fs_1.5.2         
## [25] vctrs_0.5.1       sass_0.4.4        systemfonts_1.0.4 rprojroot_2.0.3  
## [29] grid_4.2.2        glue_1.6.2        R6_2.5.1          textshaping_0.3.6
## [33] rmarkdown_2.18    purrr_0.3.5       magrittr_2.0.3    codetools_0.2-18 
## [37] htmltools_0.5.3   splines_4.2.2     shape_1.4.6       ragg_1.2.4       
## [41] stringi_1.7.8     cachem_1.0.6

References

Gibb, Sebastian. 2021. zlog: Z(log) Transformation for Laboratory Measurements. https://doi.org/10.5281/zenodo.4727117.

Hoffmann, Georg, Frank Klawonn, Ralf Lichtinghagen, and Matthias Orth. 2017. “The Zlog-Value as Basis for the Standardization of Laboratory Results.” LaboratoriumsMedizin 41 (1): 23–32. https://doi.org/10.1515/labmed-2016-0087.

Wiesner, Russell, Erick Edwards, Richard Freeman, Ann Harper, Ray Kim, Patrick Kamath, Walter Kremers, et al. 2003. “Model for End-Stage Liver Disease (MELD) and Allocation of Donor Livers.” Gastroenterology 124 (1): 91–96. https://doi.org/10.1053/gast.2003.50016.