LABOR Study

Author

Russell Lewis

Published

December 13, 2024

Background

This is the webpage summarizes ongoing analysis for the LABOR study. The figures are preliminary and in many cases I have not changed the variable indicators/legends from the original dataset (I don’t have a code book of what some the numbers represent). The figures can be aesthetically improved and reformatted before final publication. This analysis is just an initial attempt to understand the dataset and confirm a data analysis approach for the final manuscript. The working hypothesis of the analysis is that L-AMB is non-inferior to voriconazole/isavuconazole (triazole-based therapy) for the treatment of invasive aspergillosis using using Day + 90 all-cause mortality as the primary endpoint.

To save time, I did not recreate your “Table 1” analysis you forwarded to me, but used it in consideration of preparing the analysis.

Primary endpoint

The first few graphs are an attempt to just visualize the data. I started by plotting the Kaplan-Meier Curves for the entire dataset stratified by whether patients received triazoles or L-AMB.

Code
data<-read_xlsx("LABOR_definitivo.xlsx")
fit <- survfit(Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica , data = data)

summary(survfit(Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica, data = data), times = 42)
Call: survfit(formula = Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica, 
    data = data)

                terapia_antifungina_categorica=1 
        time       n.risk      n.event     survival      std.err lower 95% CI 
     42.0000     208.0000      88.0000       0.7027       0.0266       0.6525 
upper 95% CI 
      0.7567 

                terapia_antifungina_categorica=2 
        time       n.risk      n.event     survival      std.err lower 95% CI 
     42.0000      69.0000      36.0000       0.6571       0.0463       0.5723 
upper 95% CI 
      0.7545 
Code
summary(survfit(Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica, data = data), times = 90)
Call: survfit(formula = Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica, 
    data = data)

                terapia_antifungina_categorica=1 
        time       n.risk      n.event     survival      std.err lower 95% CI 
     90.0000     177.0000     122.0000       0.5878       0.0286       0.5344 
upper 95% CI 
      0.6467 

                terapia_antifungina_categorica=2 
        time       n.risk      n.event     survival      std.err lower 95% CI 
     90.0000      58.0000      49.0000       0.5333       0.0487       0.4460 
upper 95% CI 
      0.6378 
Code
Kmgraph <-ggsurvplot(
  fit,
  data = data,
  size = 1,                 # change line size
  palette =
    c("red", "#2E9FDF"),# custom color palettes
  conf.int = TRUE,          # Add confidence interval
  pval = TRUE,              # Add p-value
  risk.table = TRUE,        # Add risk table
  risk.table.col = "strata",# Risk table color by groups

  legend.labs =
    c("Triazole", "Liposomal AMB"),    # Change legend labels
  risk.table.height = 0.25, # Useful to change when you have multiple groups
  ggtheme = theme_bw()      # Change ggplot2 theme
)

Kmgraph
Figure 1: Kaplan-Meier analysis of 90-day survival rates

These data demonstrate that overall, there is no significant differences (using Log-Rank test) in the rate of 90-day mortality between patients who received L-AMB versus triazoles, although there seems to be a trend favoring the triazoles.

Comparison of ICU versus non- ICU patients

Interestingly, differences between L_ABM and triazoles is not observed in patients who were in the ICU, but patients receiving triazoles who were not in the ICU had lower mortality rates

Code
# Filter data for patients in or not in ICU
ICU_data <- filter(data, ricovero_TI == "2")
nonicu_data <- filter(data, ricovero_TI == "1")
Code
fiticu <- survfit(Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica , data = ICU_data)
Kmgraph_ICU <-ggsurvplot(
  fiticu,
  data = ICU_data,
  size = 1,                 # change line size
  palette =
    c("red", "#2E9FDF"),# custom color palettes
  conf.int = TRUE,          # Add confidence interval
  pval = TRUE,              # Add p-value
  risk.table = TRUE,        # Add risk table
  risk.table.col = "strata",# Risk table color by groups

  legend.labs =
    c("Triazole", "Liposomal AMB"),    # Change legend labels
  risk.table.height = 0.25, # Useful to change when you have multiple groups
  ggtheme = theme_bw()      # Change ggplot2 theme
)

Kmgraph_ICU
Figure 2: Kaplan-Meier analysis of 90-day survival rates in ICU patients
Code
fitnonicu <- survfit(Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica , data = nonicu_data)
Kmgraph_nonICU <-ggsurvplot(
  fitnonicu,
  data = nonicu_data,
  size = 1,                 # change line size
  palette =
    c("red", "#2E9FDF"),# custom color palettes
  conf.int = TRUE,          # Add confidence interval
  pval = TRUE,              # Add p-value
  risk.table = TRUE,        # Add risk table
  risk.table.col = "strata",# Risk table color by groups

  legend.labs =
    c("Triazole", "Liposomal AMB"),    # Change legend labels
  risk.table.height = 0.25, # Useful to change when you have multiple groups
  ggtheme = theme_bw()      # Change ggplot2 theme
)

Kmgraph_nonICU
Figure 3: Kaplan-Meier analysis of 90-day survival rates in non-ICU patients

Mortality rate distribution

To confirm that the rates of mortality are similarly distributed between the two groups I created population time plots using the casebase package1. each grey line represents the time course of a single patients (the graph is arranged from shortest to longest) with red dots indicating the time of mortality. The distribution in time to death is relatively similar between the two groups although the highest incidence density of mortality appears in the first 25 days for both groups. This is consistent with using Day +42 mortality as a more indicative endpoint for fungal infection-specific mortality

Code
library (data.table)

pt_fungal <- popTime(data = data, time="IA_to_90death_COX", event="death_3m")
class(pt_fungal)
[1] "popTime"    "data.table" "data.frame"
Code
plot(popTime(pt_fungal, exposure = "terapia_antifungina_categorica"))
Figure 4: Population time-plot of 90-day mortality, 1= Triazole; 2=Liposomal AMB; Each gray line represent 1 subject time in study. Red dots indicate time of death

I noticed in your Table 1 there was significant differences in the switching to other antifungals between L-AMB and voriconazole patients. I reset the data to day +90 for the three key time variables (LOS in hospital, time to switch and time to death by 90 days) and compared the cumulative incidence curves. We can add length of ICU stay (LIS) later if desired although it will make the graph harder to read. Overall the mortality CID curves and hospital discharge curves are similar. However These data suggest that more than 2/3 of patients who received L-AMB were switched to an alternative antifungal within two weeks. This is consistent with empirical use and best clinical practice for use of the drug to avoid nephrotoxicity,2 but creates a bias in trying to demonstrate “equivalence” of the two treatment approaches. Therefore we will mostly be comparing a strategy of starting two weeks with liposomal amphotericin B.

Analysis option

Consider a table that describes patients (n=38) with aspergillosis who did not switch from liposomal amphotericin B

Code
library (readxl)
library (ggplot2)
cif_LAMB <- read_excel("cif_LAMB.xlsx")
cif_voriconazole <- read_excel("cif_voriconazole.xlsx")

graph1<-ggplot () +
  geom_area(data = cif_LAMB, aes(x = time, y = Surv), fill = "red", alpha = 0.5) +
  geom_area(data = cif_LAMB, aes(x = time, y = Dschg), fill = "green", alpha = 0.5) +
  geom_area(data = cif_LAMB, aes(x = time, y = Switch), fill = "blue", alpha = 0.5) +
  labs(title = "Amphotericin B", x = "Days since diagnosis", y = "Incidence") + theme_minimal()

graph2<-ggplot () +
  geom_area(data = cif_voriconazole, aes(x = time, y = Surv), fill = "red", alpha = 0.5) +
  geom_area(data = cif_voriconazole, aes(x = time, y = Dschg), fill = "green", alpha = 0.5) +
  geom_area(data = cif_voriconazole, aes(x = time, y = Switch), fill = "blue", alpha = 0.5) +
  labs(title = "Voriconazole", x = "Days since diagnosis", y = "Incidence") + theme_minimal()

library("cowplot")
plot_grid(graph1, graph2,
          ncol = 2, nrow = 1)
Figure 5: Cumulative incidence function of survival (red), discharge (green) and medication switch (blue) between the two study cohorts

Indeed, if we go back and compare the Kaplan-Meier curves for liposomal AMB and voriconazole in patients who did not switch therapies, we see a significant difference in mortality by the KM curves. However, I recognize this analysis may be biased against L-AMB.

Code
Kmgraph2 <-ggsurvplot(
  fit2,
  data = filtered_data,
  size = 1,                 
  palette =
    c("red", "#2E9FDF"),
  conf.int = TRUE,         
  pval = TRUE,           
  risk.table = TRUE,      
  risk.table.col = "strata",
  legend.labs =
    c("Triazole", "Liposomal AMB"),    # Change legend labels
  risk.table.height = 0.25, # Useful to change when you have multiple groups
  ggtheme = theme_bw()      # Change ggplot2 theme
)

Kmgraph2
Figure 6: Kaplan-Meier analysis in patients who did not switch therapy

Changes in therapy

A comparison of the specific switch in therapy shows marked differences in the types of molecules that were substituted (I do not know specifically which drugs these numerical codes represent).

Code
vori_change <-ggplot(vori_df, aes(x = tp_modif_molecola, y = percent, fill = tp_modif_molecola)) +
  geom_bar(stat = "identity") +
   geom_text(aes(label = paste0(round(percent), "%")), hjust = -2, size = 4) +  # Add percent labels
  labs(title = "Triazole", x = "Molecule", y = "Percent") +
  theme_minimal() + scale_y_continuous(labels = scales::percent_format(scale = 1), limits = c(0, 100)) +
   guides(fill = "none") +  coord_flip() + scale_x_continuous(breaks = c(1, 2, 3, 4), labels = c("ISAV", "VORI", "L-AMB", "POSA"))

lamb_change <-ggplot(lamb_df, aes(x = tp_modif_molecola, y = percent, fill = tp_modif_molecola)) +
  geom_bar(stat = "identity") +
   geom_text(aes(label = paste0(round(percent), "%")), hjust = -2, size = 4) +  # Add percent labels
  labs(title = "Liposomal AMB", x = "Molecule", y = "Percent") +
  theme_minimal() + scale_y_continuous(labels = scales::percent_format(scale = 1), limits = c(0, 100)) +
   guides(fill = "none") +  coord_flip() + scale_x_continuous(breaks = c(1, 2, 3, 4), labels = c("ISAV", "VORI", "L-AMB", "POSA"))


library("cowplot")
plot_grid(vori_change, lamb_change,
          ncol = 2, nrow = 1)
Figure 7: Therapy changes by type of antifungal molecule

Matteo: I noticed there were actually 8 reasons in the original dataset as motives for changing therapy, but in your email 03.12.2024 only 7 reasons were given. What is the 8th reason?

Code
#| label: fig-change 2
#| fig-cap: "Therapy changes by reason for change"
#| warning: false
vori_change2 <-ggplot(vori_df2, aes(x = tp_modif_motivo, y = percent, fill = tp_modif_motivo)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = paste0(round(percent), "%")), hjust = -2, size = 4) +
  labs(title = "Triazole", x = "Reason for change", y = "Percent") +
  theme_minimal() + scale_y_continuous(labels = scales::percent_format(scale = 1), limits = c(0, 100)) +
   guides(fill = "none") +
  coord_flip() + scale_x_continuous(breaks = c(1, 2, 3, 4, 5, 6, 7, 8), labels = c("Oral stepdown", "Persistent IA", "Refractory IA", "Poor TDM", "DDI", "AE", "Candida breakthough", "XXX"))


lamb_change2 <-ggplot(lamb_df2, aes(x = tp_modif_motivo, y = percent, fill = tp_modif_motivo)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = paste0(round(percent), "%")), hjust = -2, size = 4) +
  labs(title = "Liposomal AMB", x = "Reason for change", y = "Percent") +
  theme_minimal() + scale_y_continuous(labels = scales::percent_format(scale = 1), limits = c(0, 100)) +  
   guides(fill = "none") + 
  coord_flip() + scale_x_continuous(breaks = c(1, 2, 3, 4, 5, 6, 7, 8), labels = c("Oral stepdown", "Persistent IA", "Refractory IA", "Poor TDM", "DDI", "AE", "Candida breakthrough", "XXXX"))

library("cowplot")
plot_grid(vori_change2, lamb_change2,
          ncol = 2, nrow = 1)


Cox regression: Survival

I then examined possible multivariable models that could potentially allow for comparisons accounting for differences in patient risk factors for 90-day mortality. Examining your univariate analysis, I included several key risk factors that would be expected or were shown in your analysis to be associated with a higher risk of 90-mortality. For the moment I did not include biomarkers (I will come back to these later). Only three variables emerged as independent risk factors for 90-mortality: CCI, fr_VAPA, and terapia_antifungina_categorica. Comparison of residuals versus linear predictors did not identify a need for modeling these as time-varying covariates (also shown by the chi-square statistics vs. residuals). Note this analysis included ICU stay longer than 14 days.

Code
res.cox <- coxph(Surv(IA_to_90death_COX, death_3m) ~ eta + CCI + fr_SOT + fr_HSCT + fr_malatt_ematol +  fr_neutropenia + fr_steroide_cronico + fr_VAPA + fr_degenzaTI_sup14gg + profilassi_antifungina + terapia_antifungina_categorica, data = data_tibble)
summary(res.cox)
Call:
coxph(formula = Surv(IA_to_90death_COX, death_3m) ~ eta + CCI + 
    fr_SOT + fr_HSCT + fr_malatt_ematol + fr_neutropenia + fr_steroide_cronico + 
    fr_VAPA + fr_degenzaTI_sup14gg + profilassi_antifungina + 
    terapia_antifungina_categorica, data = data_tibble)

  n= 401, number of events= 171 

                                    coef exp(coef)  se(coef)      z Pr(>|z|)   
eta                             0.008539  1.008576  0.007938  1.076  0.28203   
CCI                             0.097698  1.102629  0.037363  2.615  0.00893 **
fr_SOT                         -0.471556  0.624031  0.291787 -1.616  0.10607   
fr_HSCT                        -0.308537  0.734521  0.296504 -1.041  0.29807   
fr_malatt_ematol               -0.084158  0.919286  0.208580 -0.403  0.68660   
fr_neutropenia                 -0.115370  0.891037  0.264951 -0.435  0.66324   
fr_steroide_cronico            -0.093865  0.910405  0.227392 -0.413  0.67976   
fr_VAPA                         0.337957  1.402080  0.176005  1.920  0.05484 . 
fr_degenzaTI_sup14gg            0.164585  1.178904  0.254167  0.648  0.51728   
profilassi_antifungina          0.150528  1.162448  0.214695  0.701  0.48323   
terapia_antifungina_categorica  0.535144  1.707695  0.192275  2.783  0.00538 **
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

                               exp(coef) exp(-coef) lower .95 upper .95
eta                               1.0086     0.9915    0.9930     1.024
CCI                               1.1026     0.9069    1.0248     1.186
fr_SOT                            0.6240     1.6025    0.3522     1.106
fr_HSCT                           0.7345     1.3614    0.4108     1.313
fr_malatt_ematol                  0.9193     1.0878    0.6108     1.384
fr_neutropenia                    0.8910     1.1223    0.5301     1.498
fr_steroide_cronico               0.9104     1.0984    0.5830     1.422
fr_VAPA                           1.4021     0.7132    0.9930     1.980
fr_degenzaTI_sup14gg              1.1789     0.8482    0.7164     1.940
profilassi_antifungina            1.1624     0.8603    0.7632     1.771
terapia_antifungina_categorica    1.7077     0.5856    1.1715     2.489

Concordance= 0.631  (se = 0.021 )
Likelihood ratio test= 39.26  on 11 df,   p=5e-05
Wald test            = 38.77  on 11 df,   p=6e-05
Score (logrank) test = 39.04  on 11 df,   p=5e-05
Code
## Test of proportaional hazards assumption
#| label: fig-cox2
#| fig-cap: "Tests of proportional hazards assumption "
#| warning: false
test.ph <- cox.zph(res.cox)
test.ph
                                  chisq df    p
eta                            0.155110  1 0.69
CCI                            0.317143  1 0.57
fr_SOT                         0.000987  1 0.97
fr_HSCT                        0.388241  1 0.53
fr_malatt_ematol               0.687075  1 0.41
fr_neutropenia                 0.349761  1 0.55
fr_steroide_cronico            1.446334  1 0.23
fr_VAPA                        0.054621  1 0.82
fr_degenzaTI_sup14gg           0.661913  1 0.42
profilassi_antifungina         0.121841  1 0.73
terapia_antifungina_categorica 0.321447  1 0.57
GLOBAL                         5.681352 11 0.89
Code
ggcoxdiagnostics(res.cox, type = "dfbeta" , linear.predictions = TRUE)
Figure 8: Multivariable Cox regression analysis of risk factors for 90-day mortality
Code
ggforest(
 res.cox,
  data = data,
  main = "Hazard ratio",
  cpositions = c(0.02, 0.22, 0.4),
  fontsize = 0.7,
  refLabel = "reference",
  noDigits = 2
)
Figure 9: Plot of Cox regression hazard ratios

Including ICU status in the model

Based on our discussions I re-added any ICU stay in addition to 14 days stay in the ICU in the model. The results are somewhat different as VAPA drops from the model, SOT, ICU stay, CCI and category of antifungal therapy remain in the model. However, marked changes in the HR for fr_degenzaTI_sup14gg and ricovero_TI suggest a problem with colinearity in the model.

Code
res.cox2 <- coxph(Surv(IA_to_90death_COX, death_3m) ~ eta + CCI + fr_SOT + ricovero_TI + fr_HSCT + fr_malatt_ematol +  fr_neutropenia + fr_steroide_cronico + fr_VAPA + fr_degenzaTI_sup14gg + profilassi_antifungina + fr_degenzaTI_sup14gg + terapia_antifungina_categorica, data = data_tibble)
summary(res.cox2)
Call:
coxph(formula = Surv(IA_to_90death_COX, death_3m) ~ eta + CCI + 
    fr_SOT + ricovero_TI + fr_HSCT + fr_malatt_ematol + fr_neutropenia + 
    fr_steroide_cronico + fr_VAPA + fr_degenzaTI_sup14gg + profilassi_antifungina + 
    fr_degenzaTI_sup14gg + terapia_antifungina_categorica, data = data_tibble)

  n= 401, number of events= 171 

                                    coef exp(coef)  se(coef)      z Pr(>|z|)
eta                             0.013952  1.014050  0.008284  1.684 0.092142
CCI                             0.131764  1.140839  0.038051  3.463 0.000535
fr_SOT                         -0.866768  0.420308  0.299529 -2.894 0.003806
ricovero_TI                    -1.100704  0.332637  0.192258 -5.725 1.03e-08
fr_HSCT                        -0.208831  0.811532  0.296483 -0.704 0.481207
fr_malatt_ematol                0.128166  1.136742  0.214867  0.596 0.550849
fr_neutropenia                  0.092094  1.096468  0.271078  0.340 0.734058
fr_steroide_cronico            -0.063838  0.938157  0.228839 -0.279 0.780271
fr_VAPA                         0.153983  1.166472  0.180939  0.851 0.394756
fr_degenzaTI_sup14gg           -0.410430  0.663365  0.267257 -1.536 0.124608
profilassi_antifungina          0.193586  1.213594  0.216689  0.893 0.371652
terapia_antifungina_categorica  0.520655  1.683130  0.194118  2.682 0.007315
                                  
eta                            .  
CCI                            ***
fr_SOT                         ** 
ricovero_TI                    ***
fr_HSCT                           
fr_malatt_ematol                  
fr_neutropenia                    
fr_steroide_cronico               
fr_VAPA                           
fr_degenzaTI_sup14gg              
profilassi_antifungina            
terapia_antifungina_categorica ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

                               exp(coef) exp(-coef) lower .95 upper .95
eta                               1.0141     0.9861    0.9977    1.0306
CCI                               1.1408     0.8765    1.0589    1.2292
fr_SOT                            0.4203     2.3792    0.2337    0.7560
ricovero_TI                       0.3326     3.0063    0.2282    0.4849
fr_HSCT                           0.8115     1.2322    0.4539    1.4510
fr_malatt_ematol                  1.1367     0.8797    0.7460    1.7320
fr_neutropenia                    1.0965     0.9120    0.6445    1.8653
fr_steroide_cronico               0.9382     1.0659    0.5991    1.4691
fr_VAPA                           1.1665     0.8573    0.8182    1.6630
fr_degenzaTI_sup14gg              0.6634     1.5075    0.3929    1.1201
profilassi_antifungina            1.2136     0.8240    0.7936    1.8557
terapia_antifungina_categorica    1.6831     0.5941    1.1505    2.4624

Concordance= 0.675  (se = 0.02 )
Likelihood ratio test= 71.02  on 12 df,   p=2e-10
Wald test            = 66.92  on 12 df,   p=1e-09
Score (logrank) test = 68.88  on 12 df,   p=5e-10
Code
## Test of proportional hazards assumption
#| label: fig-cox3
#| fig-cap: "Tests of proportional hazards assumption with revised model "
#| warning: false
test.ph2 <- cox.zph(res.cox2)
test.ph2
                                 chisq df    p
eta                            0.18730  1 0.67
CCI                            0.38119  1 0.54
fr_SOT                         0.00144  1 0.97
ricovero_TI                    3.28644  1 0.07
fr_HSCT                        0.51167  1 0.47
fr_malatt_ematol               1.17612  1 0.28
fr_neutropenia                 0.25216  1 0.62
fr_steroide_cronico            1.43391  1 0.23
fr_VAPA                        0.05456  1 0.82
fr_degenzaTI_sup14gg           0.56184  1 0.45
profilassi_antifungina         0.05777  1 0.81
terapia_antifungina_categorica 0.19708  1 0.66
GLOBAL                         9.91700 12 0.62
Code
ggcoxdiagnostics(res.cox2, type = "dfbeta" , linear.predictions = TRUE)
Figure 10: Multivariable Cox regression analysis of risk factors for 90-day mortality including ICU
Code
ggforest(
 res.cox2,
  data = data_tibble,
  main = "Hazard ratio",
  cpositions = c(0.02, 0.22, 0.4),
  fontsize = 0.7,
  refLabel = "reference",
  noDigits = 2
)
Figure 11: Plot of Cox regression hazard ratios

Use “dove_diagnosi=3” for the ICU dummy variable

“Dove_diagnosi=3” was suggested as the best indicator value for ICU status. So I created a new dummay variable for icu “new_icu” and re-ran the cox-regression. ICU status, CCI and the type of antifungal therapy remained as independent predict variables of 90-day mortality.

Code
library(dplyr)
data <- data %>%
mutate(new_icu = ifelse(dove_diagnosi == 3, 1, 0))

res.cox3 <- coxph(Surv(IA_to_90death_COX, death_3m) ~ eta + CCI + fr_SOT + fr_HSCT + fr_malatt_ematol +  fr_neutropenia + fr_steroide_cronico + fr_VAPA + new_icu + profilassi_antifungina + terapia_antifungina_categorica, data = data)

summary(res.cox3)
Call:
coxph(formula = Surv(IA_to_90death_COX, death_3m) ~ eta + CCI + 
    fr_SOT + fr_HSCT + fr_malatt_ematol + fr_neutropenia + fr_steroide_cronico + 
    fr_VAPA + new_icu + profilassi_antifungina + terapia_antifungina_categorica, 
    data = data)

  n= 401, number of events= 171 

                                    coef exp(coef)  se(coef)      z Pr(>|z|)
eta                             0.008708  1.008746  0.008142  1.070 0.284831
CCI                             0.145908  1.157090  0.038662  3.774 0.000161
fr_SOT                         -0.471656  0.623968  0.289915 -1.627 0.103762
fr_HSCT                        -0.130195  0.877924  0.299449 -0.435 0.663720
fr_malatt_ematol                0.043461  1.044420  0.208895  0.208 0.835188
fr_neutropenia                 -0.014534  0.985571  0.267097 -0.054 0.956604
fr_steroide_cronico            -0.076896  0.925986  0.227198 -0.338 0.735022
fr_VAPA                         0.173656  1.189647  0.179473  0.968 0.333250
new_icu                         0.863647  2.371795  0.188519  4.581 4.62e-06
profilassi_antifungina          0.199423  1.220698  0.215207  0.927 0.354106
terapia_antifungina_categorica  0.600152  1.822395  0.192360  3.120 0.001809
                                  
eta                               
CCI                            ***
fr_SOT                            
fr_HSCT                           
fr_malatt_ematol                  
fr_neutropenia                    
fr_steroide_cronico               
fr_VAPA                           
new_icu                        ***
profilassi_antifungina            
terapia_antifungina_categorica ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

                               exp(coef) exp(-coef) lower .95 upper .95
eta                               1.0087     0.9913    0.9928     1.025
CCI                               1.1571     0.8642    1.0727     1.248
fr_SOT                            0.6240     1.6026    0.3535     1.101
fr_HSCT                           0.8779     1.1391    0.4882     1.579
fr_malatt_ematol                  1.0444     0.9575    0.6935     1.573
fr_neutropenia                    0.9856     1.0146    0.5839     1.664
fr_steroide_cronico               0.9260     1.0799    0.5932     1.445
fr_VAPA                           1.1896     0.8406    0.8369     1.691
new_icu                           2.3718     0.4216    1.6391     3.432
profilassi_antifungina            1.2207     0.8192    0.8006     1.861
terapia_antifungina_categorica    1.8224     0.5487    1.2500     2.657

Concordance= 0.655  (se = 0.021 )
Likelihood ratio test= 58.73  on 11 df,   p=2e-08
Wald test            = 57.58  on 11 df,   p=3e-08
Score (logrank) test = 58.62  on 11 df,   p=2e-08
Code
## Test of proportional hazards assumption
#| label: fig-cox3
#| fig-cap: "Tests of proportional hazards assumption "
#| warning: false
test.ph <- cox.zph(res.cox3)
test.ph
                                  chisq df     p
eta                            0.172440  1 0.678
CCI                            0.465316  1 0.495
fr_SOT                         0.000387  1 0.984
fr_HSCT                        0.309180  1 0.578
fr_malatt_ematol               0.660658  1 0.416
fr_neutropenia                 0.210877  1 0.646
fr_steroide_cronico            1.340167  1 0.247
fr_VAPA                        0.073137  1 0.787
new_icu                        2.977708  1 0.084
profilassi_antifungina         0.038923  1 0.844
terapia_antifungina_categorica 0.277157  1 0.599
GLOBAL                         6.913008 11 0.806
Code
ggcoxdiagnostics(res.cox, type = "dfbeta" , linear.predictions = TRUE)
Figure 12: Multivariable Cox regression analysis of risk factors for 90-day mortality
Code
ggforest(
 res.cox3,
  data = data,
  main = "Hazard ratio",
  cpositions = c(0.02, 0.22, 0.4),
  fontsize = 0.7,
  refLabel = "reference",
  noDigits = 2
)
Figure 13: Plot of Cox regression hazard ratios

Filter VAPA versus non VAPA

Very few patients with VAPA received L-AMB, therefore it is not surprising that no differences are seen when patients are stratified by VAPA

Code
novapa_data <- filter(data_tibble, fr_VAPA == "0")
vapa_data <- filter(data_tibble, fr_VAPA == "1")
fit_novapa <- survfit(Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica , data = novapa_data)
fit_vapa <- survfit(Surv(IA_to_90death_COX, death_3m) ~ terapia_antifungina_categorica , data = vapa_data)
Kmgraph_novapa <-ggsurvplot(
  fit_novapa,
  data = novapa_data,
  size = 1,                 # change line size
  palette =
    c("red", "#2E9FDF"),# custom color palettes
  conf.int = TRUE,          # Add confidence interval
  pval = TRUE,              # Add p-value
  risk.table = TRUE,        # Add risk table
  risk.table.col = "strata",# Risk table color by groups

  legend.labs =
    c("Triazole", "Liposomal AMB"),    # Change legend labels
  risk.table.height = 0.25, # Useful to change when you have multiple groups
  ggtheme = theme_bw()      # Change ggplot2 theme
)


Kmgraph_novapa
Figure 14: Comparison of Kapla-Meier Survival curves in patients without VAPA
Code
Kmgraph_vapa <-ggsurvplot(
  fit_vapa,
  data = vapa_data,
  size = 1,                 # change line size
  palette =
    c("red", "#2E9FDF"),# custom color palettes
  conf.int = TRUE,          # Add confidence interval
  pval = TRUE,              # Add p-value
  risk.table = TRUE,        # Add risk table
  risk.table.col = "strata",# Risk table color by groups

  legend.labs =
    c("Triazole", "Liposomal AMB"),    # Change legend labels
  risk.table.height = 0.25, # Useful to change when you have multiple groups
  ggtheme = theme_bw()      # Change ggplot2 theme
)

Kmgraph_vapa
Figure 15: Comparison of Kaplan-Meier Survival curves in patients with VAPA

Predicted Cox regression survival curves by treatment type

When survival curves for triazole versus L-AMB therapy were adjusted for the two independent predictors of 90-day mortality (CCI and ICU_new) we see that higher survival rates were predicted for patients in the triazole (group 1) versus liposomal AMB (group 2) treatment. The lower graph shows the estimated mortality difference over time ( nearly 10%) difference with the 95% CI climbing suprassing above zero within the first 25 days,

Code
library (survival)

library(dplyr)
data_icu <- data %>%
mutate(new_icu = ifelse(dove_diagnosi == 3, 1, 0))

data_icu$terapia_antifungina_categorica <- as.factor(data_icu$terapia_antifungina_categorica)
outcome_model <- survival::coxph(Surv(IA_to_90death_COX, death_3m) ~ CCI + new_icu + terapia_antifungina_categorica, data = data_icu, x=TRUE)
library (adjustedCurves)
adjsurv <- adjustedsurv(data=data_icu,
                        variable="terapia_antifungina_categorica",
                        ev_time="IA_to_90death_COX",
                        event="death_3m",
                        method="direct",
                        outcome_model=outcome_model,
                        conf_int=TRUE)
head(adjsurv$adj)
  time      surv group          se  ci_lower  ci_upper
1    0 1.0000000     1 0.000000000 1.0000000 1.0000000
2    2 0.9956332     1 0.003061716 0.9896324 1.0000000
3    3 0.9802604     1 0.006314479 0.9678843 0.9926366
4    4 0.9736182     1 0.007245492 0.9594173 0.9878192
5    5 0.9602218     1 0.009007023 0.9425684 0.9778752
6    6 0.9512463     1 0.010038245 0.9315717 0.9709209
Code
adjusted_curve_diff(adjsurv, times=14, conf_int=TRUE)
  time       diff         se    ci_lower  ci_upper    p_value
1   14 0.07644816 0.03712166 0.003691043 0.1492053 0.03945642
Code
adjusted_curve_diff(adjsurv, times=30, conf_int=TRUE)
  time      diff         se  ci_lower  ci_upper    p_value
1   30 0.1071701 0.04552658 0.0179396 0.1964005 0.01857207
Code
adjusted_curve_diff(adjsurv, times=42, conf_int=TRUE)
  time      diff         se   ci_lower ci_upper    p_value
1   42 0.1220078 0.04920763 0.02556262 0.218453 0.01315856
Code
adjusted_curve_diff(adjsurv, times=60, conf_int=TRUE)
  time      diff         se  ci_lower  ci_upper     p_value
1   60 0.1366415 0.05155504 0.0355955 0.2376876 0.008039633
Code
adjusted_curve_diff(adjsurv, times=90, conf_int=TRUE)
  time      diff         se   ci_lower  ci_upper     p_value
1   90 0.1439053 0.05246992 0.04106612 0.2467444 0.006095039
Code
adjusted_rmst(adjsurv, to=42, conf_int=TRUE)
  to group     rmst
1 42     1 34.99604
2 42     2 31.66834
Code
library (ggthemes)
library (ggplot2)
coxplot1 <-plot(adjsurv, conf_int=TRUE, custom_colors=c("red", "blue"), gg_theme=theme_bw(), risk_table_theme=theme_classic(),
     legend.position="top", xlab="Time (days)") +
  ylim(0, 1)
coxplot2 <-plot_curve_diff(adjsurv, conf_int=TRUE, color="blue")

library("cowplot")
plot_grid(coxplot1, coxplot2,
          ncol = 2, nrow = 1)
Figure 16: Kaplan-Meier survival curves adjusted for 90-day mortality risk factors. Top graph: Group 1= triazoles, Group 2= L-AMB; Lower graph- Estimated survival differences over time between triazole vs. L-AMB treated patients.

Cox regression predicted survival

When survival curves for triazole versus L-AMB therapy are analyzed in relation to icu_new and predictors for mortalty (icu_new, CCI) we see higher survival rates were predicted for patients in the triazole (group 1) versus liposomal AMB (group 2) treatment. The lower graph shows the estimated mortality difference over time (between 5-10%) difference with the 95% CI climbing above zero by approximately day 40.

Code
library (survival)
library(dplyr)
data_icu <- data %>%
mutate(new_icu = ifelse(dove_diagnosi == 3, 1, 0))

data_icu$terapia_antifungina_categorica <- as.factor(data_icu$terapia_antifungina_categorica)
outcome_model2 <- survival::coxph(Surv(IA_to_90death_COX, death_3m) ~ CCI + new_icu + fr_SOT + terapia_antifungina_categorica, data = data_icu, x=TRUE)
library (adjustedCurves)
adjsurv2 <- adjustedsurv(data=data_icu,
                        variable="terapia_antifungina_categorica",
                        ev_time="IA_to_90death_COX",
                        event="death_3m",
                        method="direct",
                        outcome_model=outcome_model2,
                        conf_int=TRUE)
head(adjsurv2$adj)
  time      surv group          se  ci_lower  ci_upper
1    0 1.0000000     1 0.000000000 1.0000000 1.0000000
2    2 0.9956570     1 0.003042971 0.9896928 1.0000000
3    3 0.9803445     1 0.006267595 0.9680602 0.9926287
4    4 0.9737299     1 0.007214353 0.9595900 0.9878698
5    5 0.9604270     1 0.008947477 0.9428902 0.9779637
6    6 0.9515061     1 0.009966442 0.9319723 0.9710400
Code
library (ggthemes)
library (ggplot2)
coxplot3 <-plot(adjsurv2, conf_int=TRUE, custom_colors=c("red", "blue"), gg_theme=theme_bw(), risk_table_theme=theme_classic(),
     legend.position="top", xlab="Time (days)") +
  ylim(0, 1)
coxplot4 <-plot_curve_diff(adjsurv2, conf_int=TRUE, color="blue")

library("cowplot")
plot_grid(coxplot3, coxplot4,
          ncol = 2, nrow = 1)
Figure 17: Kaplan-Meier survival curves adjusted for 90-day mortality risk factors including additional risk factors. Top graph: Group 1= triazoles, Group 2= L-AMB; Lower graph- Estimated survival differences over time between triazole vs. L-AMB treated patients.

Biomarkers

Galactomannan

I examined the relationship between serum or BAL galactomannan index versus 90-day mortality by logistic regression. A weak relationship between increasing serum galactomannan and survival was evident (left panel); but no relationship was evident by BAL GM index and mortality (right panel).

Code
library (jtools)
library (cowplot)

model1 <- glm(death_3m ~ GM_siero_valore, data = data, family = binomial)
summ(model1)
MODEL INFO:
Observations: 87 (314 missing obs. deleted)
Dependent Variable: death_3m
Type: Generalized linear model
  Family: binomial 
  Link function: logit 

MODEL FIT:
χ²(1) = 3.14, p = 0.08
Pseudo-R² (Cragg-Uhler) = 0.05
Pseudo-R² (McFadden) = 0.03
AIC = 121.46, BIC = 126.39 

Standard errors:MLE
----------------------------------------------------
                         Est.   S.E.   z val.      p
--------------------- ------- ------ -------- ------
(Intercept)             -0.48   0.34    -1.41   0.16
GM_siero_valore          0.22   0.13     1.70   0.09
----------------------------------------------------
Code
data$predicted_mortality <- predict(model1, newdata = data, type = "response")
nrow(data)
[1] 401
Code
length(predict(model1, newdata = data, type = "response"))
[1] 401
Code
effect1 <-effect_plot(model1, pred = GM_siero_valore, interval = TRUE, plot.points = TRUE, 
            jitter = 0.05)

model2 <- glm(death_3m ~ GM_BAL_valore, data = data, family = binomial)
summary (model2)

Call:
glm(formula = death_3m ~ GM_BAL_valore, family = binomial, data = data)

Coefficients:
              Estimate Std. Error z value Pr(>|z|)
(Intercept)   -0.12940    0.24355  -0.531    0.595
GM_BAL_valore -0.02891    0.05935  -0.487    0.626

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 457.06  on 332  degrees of freedom
Residual deviance: 456.82  on 331  degrees of freedom
  (68 observations deleted due to missingness)
AIC: 460.82

Number of Fisher Scoring iterations: 3
Code
data$predicted_mortality2 <- predict(model2, newdata = data, type = "response")

nrow(data)
[1] 401
Code
length(predict(model2, newdata = data, type = "response"))
[1] 401
Code
effect2 <-effect_plot(model2, pred = GM_BAL_valore, interval = TRUE, plot.points = TRUE, 
            jitter = 0.05)

library("cowplot")
plot_grid(effect1, effect2,
          ncol = 2, nrow = 1)
Figure 18: Relationship of galactomannan index in serum or BAL versus 90-day mortality

PCR

I also compared log10 transformed PCR copy data and 90-day mortality. No clear relationship between PCR copy number and mortality was evident.

Code
#| label: fig-gm
#| fig-cap: "Relationship of log-transformed serum PCR copies versus 90-day mortality"
#| warning: false
library (jtools)
library (cowplot)



data$log10_variable <- log10(data$copie_PCR)

model3 <- glm(death_3m ~log10_variable , data = data, family = binomial)
summ(model3)
MODEL INFO:
Observations: 43 (358 missing obs. deleted)
Dependent Variable: death_3m
Type: Generalized linear model
  Family: binomial 
  Link function: logit 

MODEL FIT:
χ²(1) = 0.08, p = 0.78
Pseudo-R² (Cragg-Uhler) = 0.00
Pseudo-R² (McFadden) = 0.00
AIC = 61.64, BIC = 65.16 

Standard errors:MLE
---------------------------------------------------
                        Est.   S.E.   z val.      p
-------------------- ------- ------ -------- ------
(Intercept)            -0.87   1.64    -0.53   0.59
log10_variable          0.13   0.46     0.28   0.78
---------------------------------------------------
Code
data$predicted_mortality <- predict(model3, newdata = data, type = "response")
nrow(data)
[1] 401
Code
length(predict(model3, newdata = data, type = "response"))
[1] 401
Code
effect_plot(model3, pred =log10_variable, interval = TRUE, plot.points = TRUE, 
                      jitter = 0.05)

Voriconazole TDM and Survival

First sample

In the analysis of the first sample TDM and outcome, no significant relationship was observed by linear regression between the first voriconazole TDM result and 90-day mortality.

Code
filter_tdm <- data %>%
  filter (prima_tdm_vorico > 0.05)
ggplot(filter_tdm, aes(x = prima_tdm_vorico)) +
  geom_histogram(binwidth = 2, fill = "skyblue", color = "black", alpha = 0.7) +
  labs(title = "First voriconazole TDM", x = "Concentrations (mg/L)", y = "Frequency") +
  theme_minimal()

Code
filter_tdm <- data %>%
  filter (prima_tdm_vorico > 0.05)

model4 <- glm(death_3m ~ prima_tdm_vorico, data = filter_tdm, family = binomial)
summ(model4)
MODEL INFO:
Observations: 191
Dependent Variable: death_3m
Type: Generalized linear model
  Family: binomial 
  Link function: logit 

MODEL FIT:
χ²(1) = 0.46, p = 0.50
Pseudo-R² (Cragg-Uhler) = 0.00
Pseudo-R² (McFadden) = 0.00
AIC = 261.11, BIC = 267.61 

Standard errors:MLE
-----------------------------------------------------
                          Est.   S.E.   z val.      p
---------------------- ------- ------ -------- ------
(Intercept)              -0.51   0.23    -2.25   0.02
prima_tdm_vorico          0.03   0.04     0.67   0.50
-----------------------------------------------------
Code
filter_tdm$predicted_mortality <- predict(model4, newdata = filter_tdm, type = "response")
nrow(filter_tdm)
[1] 191
Code
length(predict(model4, newdata = filter_tdm, type = "response"))
[1] 191
Code
effect4 <-effect_plot(model4, pred = prima_tdm_vorico, interval = TRUE, plot.points = TRUE, 
                      jitter = 0.05)

effect4

Relationship between second voriconazole TDM and outcome

In the analysis of the second voriconazole TDM and outcome, a significant relationship was observed by logistic regression for TDM concentrations and 90-survival. Hower it appears that patients with very high voriconazole TDM concentrations had higher mortality, which may be a reflection of organ failure.

Code
filter_tdm2 <- data %>%
  filter (seconda_tdm_vorico > 0.05)
ggplot(filter_tdm2, aes(x = seconda_tdm_vorico)) +
  geom_histogram(binwidth = 2, fill = "skyblue", color = "black", alpha = 0.7) +
  labs(title = "Second voriconazole TDM", x = "Concentrations (mg/L)", y = "Frequency") +
  theme_minimal()

Code
filter_tdm2 <- data %>%
  filter (seconda_tdm_vorico > 0.05)

model5 <- glm(death_3m ~ seconda_tdm_vorico, data = filter_tdm2, family = binomial)
summ(model5)
MODEL INFO:
Observations: 147
Dependent Variable: death_3m
Type: Generalized linear model
  Family: binomial 
  Link function: logit 

MODEL FIT:
χ²(1) = 7.54, p = 0.01
Pseudo-R² (Cragg-Uhler) = 0.07
Pseudo-R² (McFadden) = 0.04
AIC = 188.65, BIC = 194.64 

Standard errors:MLE
-------------------------------------------------------
                            Est.   S.E.   z val.      p
------------------------ ------- ------ -------- ------
(Intercept)                -1.26   0.32    -3.98   0.00
seconda_tdm_vorico          0.15   0.06     2.66   0.01
-------------------------------------------------------
Code
filter_tdm2$predicted_mortality <- predict(model5, newdata = filter_tdm2, type = "response")
nrow(filter_tdm2)
[1] 147
Code
length(predict(model4, newdata = filter_tdm2, type = "response"))
[1] 147
Code
effect5 <-effect_plot(model5, pred = seconda_tdm_vorico, interval = TRUE, plot.points = TRUE, 
                      jitter = 0.05)

effect5

Code
library (rpart)
library (rpart.plot)
fit.tree = rpart(death_3m ~ seconda_tdm_vorico, data=filter_tdm2, method = "class", cp=0.008)
fit.tree
n= 147 

node), split, n, loss, yval, (yprob)
      * denotes terminal node

 1) root 147 53 0 (0.6394558 0.3605442)  
   2) seconda_tdm_vorico< 4.15 81 20 0 (0.7530864 0.2469136)  
     4) seconda_tdm_vorico>=3.75 10  0 0 (1.0000000 0.0000000) *
     5) seconda_tdm_vorico< 3.75 71 20 0 (0.7183099 0.2816901)  
      10) seconda_tdm_vorico< 2.3 45 11 0 (0.7555556 0.2444444) *
      11) seconda_tdm_vorico>=2.3 26  9 0 (0.6538462 0.3461538)  
        22) seconda_tdm_vorico>=2.75 18  4 0 (0.7777778 0.2222222) *
        23) seconda_tdm_vorico< 2.75 8  3 1 (0.3750000 0.6250000) *
   3) seconda_tdm_vorico>=4.15 66 33 0 (0.5000000 0.5000000)  
     6) seconda_tdm_vorico< 7.35 41 18 0 (0.5609756 0.4390244)  
      12) seconda_tdm_vorico>=5.85 12  3 0 (0.7500000 0.2500000) *
      13) seconda_tdm_vorico< 5.85 29 14 1 (0.4827586 0.5172414)  
        26) seconda_tdm_vorico>=4.85 19  9 0 (0.5263158 0.4736842) *
        27) seconda_tdm_vorico< 4.85 10  4 1 (0.4000000 0.6000000) *
     7) seconda_tdm_vorico>=7.35 25 10 1 (0.4000000 0.6000000) *
Code
rpart.plot(fit.tree)

Summary

  • In this retrospective analysis, patients who initially received triazole-based regimens are predicted to have improved survival versus liposomal AMB

    • This difference is still evident after controlling for several confounding factors

    • Comparisons are complicated by frequent switching of therapy- i.e. patients who are clinically resposing tp L-AMB are probably switched to triazoles

    • Stratified analysis is of interest but reduced the power; so no differences are seen between regimens

  • There was a modest relationship between serum GM index and 90-day mortality, but no clear relationship between BAL GM index or serum PCR copies and mortality

  • Overall survival curves were consistent with those previously reported in the literature

Changelog

  • Separation of ICU vs non-ICU -Completed
  • Inclusion of ICU in MV model -Completed
  • Separation of VAPA -Completed
  • Multistate analysis by type of therapy? - not attempted because of power issues
  • 11.12.2024: Request to use “dove_diagnosi_3” for ICU variable in the Cox regression -Completed
  • 11.12.2024: I will also examine relationship of TDM endpoints with outcomes - in progress

References

1.
Bhatnagar, S., Turgeon, M., Islam, J., Saarela, O. & Hanley, J. Casebase: An alternative framework for survival analysis and comparison of event rates. 14, (2022).
2.