Summary of
Results
Once the model has been run, we can use the results and summarize
them using the summary_results_det() to print the results
of the last simulation (if nsim = 1, it’s the deterministic
case), and summary_results_sim() to show the PSA results
(with the confidence intervals). We can also use the individual patient
data generated by the simulation, which we collect here to plot in the
psa_ipd object.
summary_results_det(results[[1]][[1]]) #print first simulation
#> int noint
#> costs 71261.66 63063.40
#> dcosts 0.00 8198.25
#> lys 11.21 11.08
#> dlys 0.00 0.12
#> qalys 6.98 6.63
#> dqalys 0.00 0.35
#> ICER NA 66484.18
#> ICUR NA 23296.79
#> INMB NA 9396.99
#> costs_undisc 118130.54 104038.82
#> dcosts_undisc 0.00 14091.72
#> lys_undisc 17.48 17.22
#> dlys_undisc 0.00 0.26
#> qalys_undisc 10.37 9.85
#> dqalys_undisc 0.00 0.52
#> ICER_undisc NA 54006.07
#> ICUR_undisc NA 27003.04
#> INMB_undisc NA 12001.13
#> c_default 71261.66 63063.40
#> dc_default 0.00 8198.25
#> c_default_undisc 118130.54 104038.82
#> dc_default_undisc 0.00 14091.72
#> q_default 6.98 6.63
#> dq_default 0.00 0.35
#> q_default_undisc 10.37 9.85
#> dq_default_undisc 0.00 0.52
summary_results_sim(results[[1]])
#> int noint
#> costs 71,262 (71,262; 71,262) 63,063 (63,063; 63,063)
#> dcosts 0 (0; 0) 8,198 (8,198; 8,198)
#> lys 11.2 (11.2; 11.2) 11.1 (11.1; 11.1)
#> dlys 0 (0; 0) 0.123 (0.123; 0.123)
#> qalys 6.98 (6.98; 6.98) 6.63 (6.63; 6.63)
#> dqalys 0 (0; 0) 0.352 (0.352; 0.352)
#> ICER NaN (NA; NA) 66,484 (66,484; 66,484)
#> ICUR NaN (NA; NA) 23,297 (23,297; 23,297)
#> INMB NaN (NA; NA) 9,397 (9,397; 9,397)
#> costs_undisc 118,131 (118,131; 118,131) 104,039 (104,039; 104,039)
#> dcosts_undisc 0 (0; 0) 14,092 (14,092; 14,092)
#> lys_undisc 17.5 (17.5; 17.5) 17.2 (17.2; 17.2)
#> dlys_undisc 0 (0; 0) 0.261 (0.261; 0.261)
#> qalys_undisc 10.4 (10.4; 10.4) 9.85 (9.85; 9.85)
#> dqalys_undisc 0 (0; 0) 0.522 (0.522; 0.522)
#> ICER_undisc NaN (NA; NA) 54,006 (54,006; 54,006)
#> ICUR_undisc NaN (NA; NA) 27,003 (27,003; 27,003)
#> INMB_undisc NaN (NA; NA) 12,001 (12,001; 12,001)
#> c_default 71,262 (71,262; 71,262) 63,063 (63,063; 63,063)
#> dc_default 0 (0; 0) 8,198 (8,198; 8,198)
#> c_default_undisc 118,131 (118,131; 118,131) 104,039 (104,039; 104,039)
#> dc_default_undisc 0 (0; 0) 14,092 (14,092; 14,092)
#> q_default 6.98 (6.98; 6.98) 6.63 (6.63; 6.63)
#> dq_default 0 (0; 0) 0.352 (0.352; 0.352)
#> q_default_undisc 10.4 (10.4; 10.4) 9.85 (9.85; 9.85)
#> dq_default_undisc 0 (0; 0) 0.522 (0.522; 0.522)
summary_results_sens(results)
#> arm analysis analysis_name variable value
#> <char> <int> <char> <fctr> <char>
#> 1: int 1 costs 71,262 (71,262; 71,262)
#> 2: noint 1 costs 63,063 (63,063; 63,063)
#> 3: int 1 dcosts 0 (0; 0)
#> 4: noint 1 dcosts 8,198 (8,198; 8,198)
#> 5: int 1 lys 11.2 (11.2; 11.2)
#> 6: noint 1 lys 11.1 (11.1; 11.1)
#> 7: int 1 dlys 0 (0; 0)
#> 8: noint 1 dlys 0.123 (0.123; 0.123)
#> 9: int 1 qalys 6.98 (6.98; 6.98)
#> 10: noint 1 qalys 6.63 (6.63; 6.63)
#> 11: int 1 dqalys 0 (0; 0)
#> 12: noint 1 dqalys 0.352 (0.352; 0.352)
#> 13: int 1 ICER NaN (NA; NA)
#> 14: noint 1 ICER 66,484 (66,484; 66,484)
#> 15: int 1 ICUR NaN (NA; NA)
#> 16: noint 1 ICUR 23,297 (23,297; 23,297)
#> 17: int 1 INMB NaN (NA; NA)
#> 18: noint 1 INMB 9,397 (9,397; 9,397)
#> 19: int 1 costs_undisc 118,131 (118,131; 118,131)
#> 20: noint 1 costs_undisc 104,039 (104,039; 104,039)
#> 21: int 1 dcosts_undisc 0 (0; 0)
#> 22: noint 1 dcosts_undisc 14,092 (14,092; 14,092)
#> 23: int 1 lys_undisc 17.5 (17.5; 17.5)
#> 24: noint 1 lys_undisc 17.2 (17.2; 17.2)
#> 25: int 1 dlys_undisc 0 (0; 0)
#> 26: noint 1 dlys_undisc 0.261 (0.261; 0.261)
#> 27: int 1 qalys_undisc 10.4 (10.4; 10.4)
#> 28: noint 1 qalys_undisc 9.85 (9.85; 9.85)
#> 29: int 1 dqalys_undisc 0 (0; 0)
#> 30: noint 1 dqalys_undisc 0.522 (0.522; 0.522)
#> 31: int 1 ICER_undisc NaN (NA; NA)
#> 32: noint 1 ICER_undisc 54,006 (54,006; 54,006)
#> 33: int 1 ICUR_undisc NaN (NA; NA)
#> 34: noint 1 ICUR_undisc 27,003 (27,003; 27,003)
#> 35: int 1 INMB_undisc NaN (NA; NA)
#> 36: noint 1 INMB_undisc 12,001 (12,001; 12,001)
#> 37: int 1 c_default 71,262 (71,262; 71,262)
#> 38: noint 1 c_default 63,063 (63,063; 63,063)
#> 39: int 1 dc_default 0 (0; 0)
#> 40: noint 1 dc_default 8,198 (8,198; 8,198)
#> 41: int 1 c_default_undisc 118,131 (118,131; 118,131)
#> 42: noint 1 c_default_undisc 104,039 (104,039; 104,039)
#> 43: int 1 dc_default_undisc 0 (0; 0)
#> 44: noint 1 dc_default_undisc 14,092 (14,092; 14,092)
#> 45: int 1 q_default 6.98 (6.98; 6.98)
#> 46: noint 1 q_default 6.63 (6.63; 6.63)
#> 47: int 1 dq_default 0 (0; 0)
#> 48: noint 1 dq_default 0.352 (0.352; 0.352)
#> 49: int 1 q_default_undisc 10.4 (10.4; 10.4)
#> 50: noint 1 q_default_undisc 9.85 (9.85; 9.85)
#> 51: int 1 dq_default_undisc 0 (0; 0)
#> 52: noint 1 dq_default_undisc 0.522 (0.522; 0.522)
#> arm analysis analysis_name variable value
psa_ipd <- bind_rows(map(results[[1]], "merged_df"))
psa_ipd[1:10,] |>
kable() |>
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
|
evtname
|
evttime
|
prevtime
|
pat_id
|
arm
|
total_lys
|
total_qalys
|
total_costs
|
total_costs_undisc
|
total_qalys_undisc
|
total_lys_undisc
|
lys
|
qalys
|
costs
|
lys_undisc
|
qalys_undisc
|
costs_undisc
|
c_default
|
q_default
|
c_default_undisc
|
q_default_undisc
|
nexttime
|
simulation
|
sensitivity
|
|
sick
|
0.000
|
0.000
|
1
|
int
|
1.965
|
1.572
|
7860
|
8138
|
1.628
|
2.034
|
1.965
|
1.572
|
7860
|
2.034
|
1.628
|
8138
|
7860
|
1.572
|
8138
|
1.628
|
2.034
|
1
|
1
|
|
death
|
2.034
|
0.000
|
1
|
int
|
1.965
|
1.572
|
7860
|
8138
|
1.628
|
2.034
|
0.000
|
0.000
|
0
|
0.000
|
0.000
|
0
|
0
|
0.000
|
0
|
0.000
|
2.034
|
1
|
1
|
|
sick
|
0.000
|
0.000
|
2
|
int
|
4.811
|
2.709
|
34439
|
37953
|
2.938
|
5.259
|
1.012
|
0.809
|
4047
|
1.030
|
0.824
|
4119
|
4047
|
0.809
|
4119
|
0.824
|
1.030
|
1
|
1
|
|
sicker
|
1.030
|
0.000
|
2
|
int
|
4.811
|
2.709
|
34439
|
37953
|
2.938
|
5.259
|
3.799
|
1.900
|
30392
|
4.229
|
2.115
|
33834
|
30392
|
1.900
|
33834
|
2.115
|
5.259
|
1
|
1
|
|
death
|
5.259
|
1.030
|
2
|
int
|
4.811
|
2.709
|
34439
|
37953
|
2.938
|
5.259
|
0.000
|
0.000
|
0
|
0.000
|
0.000
|
0
|
0
|
0.000
|
0
|
0.000
|
5.259
|
1
|
1
|
|
sick
|
0.000
|
0.000
|
3
|
int
|
0.807
|
0.512
|
5011
|
5094
|
0.518
|
0.819
|
0.362
|
0.289
|
1446
|
0.364
|
0.291
|
1455
|
1446
|
0.289
|
1455
|
0.291
|
0.364
|
1
|
1
|
|
sicker
|
0.364
|
0.000
|
3
|
int
|
0.807
|
0.512
|
5011
|
5094
|
0.518
|
0.819
|
0.446
|
0.223
|
3565
|
0.455
|
0.227
|
3638
|
3565
|
0.223
|
3638
|
0.227
|
0.819
|
1
|
1
|
|
death
|
0.819
|
0.364
|
3
|
int
|
0.807
|
0.512
|
5011
|
5094
|
0.518
|
0.819
|
0.000
|
0.000
|
0
|
0.000
|
0.000
|
0
|
0
|
0.000
|
0
|
0.000
|
0.819
|
1
|
1
|
|
sick
|
0.000
|
0.000
|
4
|
int
|
9.356
|
5.738
|
60714
|
75252
|
6.775
|
11.290
|
3.533
|
2.826
|
14131
|
3.767
|
3.013
|
15066
|
14131
|
2.826
|
15066
|
3.013
|
3.767
|
1
|
1
|
|
sicker
|
3.767
|
0.000
|
4
|
int
|
9.356
|
5.738
|
60714
|
75252
|
6.775
|
11.290
|
5.823
|
2.911
|
46583
|
7.523
|
3.762
|
60186
|
46583
|
2.911
|
60186
|
3.762
|
11.290
|
1
|
1
|
We can also check what has been the absolute number of events per
strategy.
|
arm
|
evtname
|
n
|
|
int
|
death
|
1000
|
|
int
|
sick
|
1000
|
|
int
|
sicker
|
733
|
|
noint
|
death
|
1000
|
|
noint
|
sick
|
1000
|
|
noint
|
sicker
|
785
|
Plots
We now use the data output to plot the histograms/densities of the
simulation.
data_plot <- results[[1]][[1]]$merged_df |>
filter(evtname != "sick") |>
group_by(arm,evtname,simulation) |>
mutate(median = median(evttime)) |>
ungroup()
ggplot(data_plot) +
geom_density(aes(fill = arm, x = evttime),
alpha = 0.7) +
geom_vline(aes(xintercept=median,col=arm)) +
facet_wrap( ~ evtname, scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
scale_x_continuous(expand = c(0, 0)) +
theme_bw()

We can also plot the patient level incremental QALY/costs.
data_qaly_cost<- psa_ipd[,.SD[1],by=.(pat_id,arm,simulation)][,.(arm,qaly=total_qalys,cost=total_costs,pat_id,simulation)]
data_qaly_cost[,ps_id:=paste(pat_id,simulation,sep="_")]
mean_data_qaly_cost <- data_qaly_cost |> group_by(arm) |> summarise(across(where(is.numeric),mean))
ggplot(data_qaly_cost,aes(x=qaly, y = cost, col = arm)) +
geom_point(alpha=0.15,shape = 21) +
geom_point(data=mean_data_qaly_cost, aes(x=qaly, y = cost, fill = arm), shape = 21,col="black",size=3) +
scale_y_continuous(expand = c(0, 0)) +
scale_x_continuous(expand = c(0, 0)) +
theme_bw()+
theme(axis.text.x = element_text(angle = 90, vjust = .5))
