knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file())
# set global chunk options
knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE,
fig.width = 12,
fig.asp = 0.8 ,
out.width = "120%")
# this options for word export
#knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
options(stringsAsFactors = F)
# always show NA is there is any in the table function
table = function (..., useNA = 'ifany') base::table(..., useNA = useNA)
library(ggplot2)
library(writexl)
library(ggpubr)
library(RColorBrewer)
library(dplyr)
library(arsenal)
library(rsimsum)
library(gt)
library(gtsummary)
mycontrols = tableby.control(numeric.stats=c("Nmiss","mean", "sd", "medianq1q3", "range"),
cat.stats=c("Nmiss", "countpct"),
stats.labels=list(Nmiss='Missing values', medianq1q3='Median (Q1, Q3)'),
test = F)
colors <- brewer.pal(8, "Dark2")
nsim <- 100
#define simulation scenarios
grid = expand.grid(
sim = 1:nsim
, N = c(500, 1000)
, p = c(0.1, 0.3, 0.5)
, AUC_0 = c(0.85)
, r = c(0.5)
, pm = c(0.3)
, mech = c("MNAR")
, type = c("MID")
)
# methods to be compared
methods <- c("CCA", "MI2", "MIB2", "HDEL", "KER", "mice", "mix", "AIPW")
Abbreviation = names(grid)
setup <- data.frame(
Abbreviation = names(grid),
Parameter = c("Number of simulations", "Sample size", "prevalence of the target condition", "True AUC", "Correlation between index test and covariates", "proportion of missing values", "Missingness Mechanism", "Type"),
Values = c(
nsim,
sapply(Abbreviation[2:length(Abbreviation)], function(x) (paste(unique(grid[,x]), collapse = ',')))
)
)
setup %>%
gt() %>%
tab_style(style = cell_text(weight = "bold"), locations = cells_column_labels(columns=c("Abbreviation", "Parameter", "Values"))) %>%
tab_header(
title = "Table 1. Overview of simulation parameter"
)
| Table 1. Overview of simulation parameter | ||
| Abbreviation | Parameter | Values |
|---|---|---|
| sim | Number of simulations | 100 |
| N | Sample size | 500,1000 |
| p | prevalence of the target condition | 0.1,0.3,0.5 |
| AUC_0 | True AUC | 0.85 |
| r | Correlation between index test and covariates | 0.5 |
| pm | proportion of missing values | 0.3 |
| mech | Missingness Mechanism | MNAR |
| type | Type | MID |
Table 2. Overview of methods
| Methods | |
|---|---|
| CCA | Complete case analysis |
| MI2 | Multiple Imputation using prediction and propensity score (Long et al. 2011a) |
| MIB2 | MI2 + bootstrap step for calculating confidence intervals (Long et al. 2011a) |
| HDEL | Hot Deck Empirical Likelihood Approach (Wang and Qin 2012, 2014) |
| KER | Kernel-based Inverse Probability Weighting (Bianco et al. 2023) |
| mice | Multiple Imputation using chained equations (van Buuren et al. 2011) |
| mix | Multiple Imputation using joint modelling (Schafer 2022) |
| AIPW | Augmented Inverse Probability Weighting (Long et al. 2011b) |
The seed for the parallel loop was set to 5273 and to 4730xi for data generation.
# due to time reasons the simulation is not conducted but the data are loaded in the following chunk
source("./Analyse/Simulation_mnar.R")
Load the simulation results
name <- "results_mnar"
load(file = paste0("./Analyse/hpc/Simulation_data/", name, ".Rdata"))
res <- res %>%
rename(r = korr) %>%
select(-type)
The following performance parameter will be calculated: number of missing values, bias, root mean squared error, empirical standard deviation, coverage, bias-eliminated coverage and power as well as the respective monte carlo standard errors for each performance parameter.
fix_col <- c("N","p","AUC_0","r", "pm","mech", "AUC_min","scenario")
source("Analyse/Simulation_performance3.R")
# input: res (file with simulation results as dataframe)
# out: raw_res (res + step 1 of performance calculation -> 1 row for each simulation run), scenario_res (dataframe with performance parameters, -> 1 row for each scenario aggregated over the runs)
# rearrange the scenario_res table columns, so that performance estimate and its MC standard error are located side by side
vars=list()
for (i in 1:length(methods)){
vars_i <- grep(methods[i], names(scenario_res), value = T)
vars[[i]] <- vars_i
}
vars_order <- unlist(vars)
dat_table1 <- scenario_res[,c(8,1:6)]
dat_table2 <- scenario_res[,vars_order]
dat_table <- cbind(dat_table1, dat_table2)
rownames(dat_table) <- NULL
# label selected variables in dat_table
dat_table <- dat_table %>%
sjlabelled::var_labels(
scenario = "Scenario",
N = "Sample size",
p = "Prevalence of target condition",
AUC_0 = "True AUC",
r = "Correlation",
pm = "Proportion of missing values",
mech = "Missingness mechanism",
av.time.AUC.CCA = "Average running time for CCA",
av.time.AUC.MI2 = "Average running time for MI2",
av.time.AUC.MIB2 = "Average running time for MIB2",
av.time.AUC.HDEL = "Average running time for HDEL",
av.time.AUC.mice = "Average running time for mice",
av.time.AUC.mix = "Average running time for mix",
av.time.AUC.AIPW = "Average running time for AIPW",
av.time.AUC.KER = "Average running time for KER"
)
# show table for bias
bias <- grep("bias", names(dat_table), value = FALSE)
knitr::kable(dat_table[,c(1:7,bias)], "simple",
col.names = gsub("[.]", " ", names(dat_table[,c(1:7,bias)])),
caption = "Table 3. Bias and its Monte Carlo Standard Error for each method",
digits = 4, format.args = list(scientific = FALSE))
| scenario | N | p | AUC_0 | r | pm | mech | bias AUC CCA | MCE bias AUC CCA | bias AUC MI2 | MCE bias AUC MI2 | bias AUC MIB2 | MCE bias AUC MIB2 | bias AUC HDEL | MCE bias AUC HDEL | bias AUC KER | MCE bias AUC KER | bias AUC mice | MCE bias AUC mice | bias AUC mix | MCE bias AUC mix | bias AUC AIPW | MCE bias AUC AIPW |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 500 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.0085 | 0.0033 | 0.0024 | 0.0034 | 0.0033 | 0.0034 | 0.0089 | 0.0035 | -0.0010 | 0.0034 | -0.0014 | 0.0032 | -0.0017 | 0.0032 | -0.0004 | 0.0032 |
| 2 | 1000 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.0121 | 0.0018 | 0.0056 | 0.0022 | 0.0049 | 0.0024 | 0.0123 | 0.0020 | 0.0045 | 0.0021 | 0.0027 | 0.0020 | 0.0025 | 0.0019 | 0.0038 | 0.0022 |
| 3 | 500 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.0188 | 0.0020 | 0.0080 | 0.0021 | 0.0098 | 0.0021 | 0.0188 | 0.0020 | 0.0065 | 0.0020 | 0.0080 | 0.0020 | 0.0074 | 0.0019 | 0.0074 | 0.0020 |
| 4 | 1000 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.0196 | 0.0013 | 0.0118 | 0.0015 | 0.0106 | 0.0015 | 0.0196 | 0.0015 | 0.0101 | 0.0014 | 0.0105 | 0.0015 | 0.0103 | 0.0014 | 0.0099 | 0.0014 |
| 5 | 500 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.0171 | 0.0021 | 0.0092 | 0.0022 | 0.0100 | 0.0022 | 0.0187 | 0.0022 | 0.0058 | 0.0021 | 0.0085 | 0.0020 | 0.0081 | 0.0021 | 0.0073 | 0.0020 |
| 6 | 1000 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.0232 | 0.0013 | 0.0127 | 0.0014 | 0.0135 | 0.0014 | 0.0233 | 0.0015 | 0.0115 | 0.0014 | 0.0126 | 0.0013 | 0.0128 | 0.0013 | 0.0118 | 0.0013 |
# show table for RMSE
mse <- grep("MSE", names(dat_table), value = FALSE)
knitr::kable(dat_table[,c(1:7,mse)], "simple",
col.names = gsub("[.]", " ", names(dat_table[,c(1:7,mse)])),
caption = "Table 4. Rot mean squared error and its Monte Carlo Standard Error for each method",
digits = 4, format.args = list(scientific = FALSE))
| scenario | N | p | AUC_0 | r | pm | mech | RMSE AUC CCA | MCE MSE AUC CCA | RMSE AUC MI2 | MCE MSE AUC MI2 | RMSE AUC MIB2 | MCE MSE AUC MIB2 | RMSE AUC HDEL | MCE MSE AUC HDEL | RMSE AUC KER | MCE MSE AUC KER | RMSE AUC mice | MCE MSE AUC mice | RMSE AUC mix | MCE MSE AUC mix | RMSE AUC AIPW | MCE MSE AUC AIPW |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 500 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.0337 | 0.0002 | 0.0342 | 0.0002 | 0.0343 | 0.0001 | 0.0360 | 0.0002 | 0.0337 | 0.0002 | 0.0316 | 0.0001 | 0.0322 | 0.0001 | 0.0320 | 0.0001 |
| 2 | 1000 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.0218 | 0.0001 | 0.0230 | 0.0001 | 0.0245 | 0.0001 | 0.0232 | 0.0001 | 0.0213 | 0.0001 | 0.0202 | 0.0001 | 0.0195 | 0.0001 | 0.0217 | 0.0001 |
| 3 | 500 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.0273 | 0.0001 | 0.0226 | 0.0001 | 0.0234 | 0.0001 | 0.0275 | 0.0001 | 0.0210 | 0.0001 | 0.0215 | 0.0001 | 0.0208 | 0.0001 | 0.0210 | 0.0001 |
| 4 | 1000 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.0237 | 0.0001 | 0.0187 | 0.0000 | 0.0180 | 0.0000 | 0.0246 | 0.0001 | 0.0175 | 0.0000 | 0.0179 | 0.0000 | 0.0172 | 0.0000 | 0.0172 | 0.0000 |
| 5 | 500 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.0269 | 0.0001 | 0.0235 | 0.0001 | 0.0244 | 0.0001 | 0.0291 | 0.0001 | 0.0212 | 0.0001 | 0.0220 | 0.0001 | 0.0224 | 0.0001 | 0.0216 | 0.0001 |
| 6 | 1000 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.0263 | 0.0001 | 0.0185 | 0.0000 | 0.0192 | 0.0000 | 0.0278 | 0.0001 | 0.0177 | 0.0000 | 0.0179 | 0.0000 | 0.0181 | 0.0000 | 0.0175 | 0.0000 |
# show table for empSE
empse <- grep("empSE", names(dat_table), value = FALSE)
knitr::kable(dat_table[,c(1:7,empse)], "simple",
col.names = gsub("[.]", " ", names(dat_table[,c(1:7,empse)])),
caption = "Table 5. Empirical Standard Error and its Monte Carlo Standard Error for each method",
digits = 4, format.args = list(scientific = FALSE))
| scenario | N | p | AUC_0 | r | pm | mech | empSE AUC CCA | MCE empSE AUC CCA | empSE AUC MI2 | MCE empSE AUC MI2 | empSE AUC MIB2 | MCE empSE AUC MIB2 | empSE AUC HDEL | MCE empSE AUC HDEL | empSE AUC KER | MCE empSE AUC KER | empSE AUC mice | MCE empSE AUC mice | empSE AUC mix | MCE empSE AUC mix | empSE AUC AIPW | MCE empSE AUC AIPW |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 500 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.0328 | 0.0023 | 0.0343 | 0.0024 | 0.0343 | 0.0024 | 0.0350 | 0.0025 | 0.0339 | 0.0024 | 0.0318 | 0.0023 | 0.0324 | 0.0023 | 0.0321 | 0.0023 |
| 2 | 1000 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.0183 | 0.0013 | 0.0224 | 0.0016 | 0.0241 | 0.0017 | 0.0197 | 0.0014 | 0.0210 | 0.0015 | 0.0201 | 0.0014 | 0.0195 | 0.0014 | 0.0215 | 0.0015 |
| 3 | 500 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.0199 | 0.0014 | 0.0213 | 0.0015 | 0.0213 | 0.0015 | 0.0202 | 0.0014 | 0.0200 | 0.0014 | 0.0201 | 0.0014 | 0.0195 | 0.0014 | 0.0198 | 0.0014 |
| 4 | 1000 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.0133 | 0.0009 | 0.0146 | 0.0010 | 0.0146 | 0.0010 | 0.0150 | 0.0011 | 0.0143 | 0.0010 | 0.0146 | 0.0010 | 0.0139 | 0.0010 | 0.0141 | 0.0010 |
| 5 | 500 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.0209 | 0.0015 | 0.0217 | 0.0015 | 0.0224 | 0.0016 | 0.0224 | 0.0016 | 0.0205 | 0.0015 | 0.0204 | 0.0015 | 0.0211 | 0.0015 | 0.0205 | 0.0015 |
| 6 | 1000 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.0126 | 0.0009 | 0.0135 | 0.0010 | 0.0137 | 0.0010 | 0.0152 | 0.0011 | 0.0136 | 0.0010 | 0.0128 | 0.0009 | 0.0128 | 0.0009 | 0.0129 | 0.0009 |
# show table for coverage
cov <- grep("cov", names(dat_table), value = FALSE)
knitr::kable(dat_table[,c(1:7,cov)], "simple",
col.names = gsub("[.]", " ", names(dat_table[,c(1:7,cov)])),
caption = "Table 6. Coverage and its Monte Carlo Standard Error for each method",
digits = 4, format.args = list(scientific = FALSE))
| scenario | N | p | AUC_0 | r | pm | mech | cov AUC CCA | MCE cov AUC CCA | cov_be AUC CCA | MCE cov_be AUC CCA | cov AUC MI2 | MCE cov AUC MI2 | cov_be AUC MI2 | MCE cov_be AUC MI2 | cov AUC MIB2 | MCE cov AUC MIB2 | cov_be AUC MIB2 | MCE cov_be AUC MIB2 | cov AUC HDEL | MCE cov AUC HDEL | cov_be AUC HDEL | MCE cov_be AUC HDEL | cov AUC KER | MCE cov AUC KER | cov_be AUC KER | MCE cov_be AUC KER | cov AUC mice | MCE cov AUC mice | cov_be AUC mice | MCE cov_be AUC mice | cov AUC mix | MCE cov AUC mix | cov_be AUC mix | MCE cov_be AUC mix | cov AUC AIPW | MCE cov AUC AIPW | cov_be AUC AIPW | MCE cov_be AUC AIPW |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 500 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.90 | 0.0300 | 0.93 | 0.0255 | 0.88 | 0.0325 | 0.94 | 0.0237 | 0.96 | 0.0196 | 0.94 | 0.0237 | 0.99 | 0.0099 | 0.93 | 0.0255 | 0.96 | 0.0196 | 0.95 | 0.0218 | 0.94 | 0.0237 | 0.95 | 0.0218 | 0.93 | 0.0255 | 0.95 | 0.0218 | 0.95 | 0.0218 | 0.95 | 0.0218 |
| 2 | 1000 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.89 | 0.0313 | 0.96 | 0.0196 | 0.86 | 0.0347 | 0.92 | 0.0271 | 0.96 | 0.0196 | 0.92 | 0.0271 | 0.99 | 0.0099 | 0.96 | 0.0196 | 0.95 | 0.0218 | 0.92 | 0.0271 | 0.95 | 0.0218 | 0.92 | 0.0271 | 0.94 | 0.0237 | 0.92 | 0.0271 | 0.90 | 0.0300 | 0.92 | 0.0271 |
| 3 | 500 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.84 | 0.0367 | 0.95 | 0.0218 | 0.87 | 0.0336 | 0.97 | 0.0171 | 0.97 | 0.0171 | 0.96 | 0.0196 | 1.00 | 0.0000 | 0.95 | 0.0218 | 0.94 | 0.0237 | 0.97 | 0.0171 | 0.92 | 0.0271 | 0.97 | 0.0171 | 0.95 | 0.0218 | 0.97 | 0.0171 | 0.93 | 0.0255 | 0.97 | 0.0171 |
| 4 | 1000 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.70 | 0.0458 | 0.93 | 0.0255 | 0.83 | 0.0376 | 0.95 | 0.0218 | 0.97 | 0.0171 | 0.95 | 0.0218 | 0.98 | 0.0140 | 0.93 | 0.0255 | 0.89 | 0.0313 | 0.95 | 0.0218 | 0.90 | 0.0300 | 0.95 | 0.0218 | 0.89 | 0.0313 | 0.95 | 0.0218 | 0.89 | 0.0313 | 0.95 | 0.0218 |
| 5 | 500 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.78 | 0.0414 | 0.93 | 0.0255 | 0.83 | 0.0376 | 0.93 | 0.0255 | 0.95 | 0.0218 | 0.94 | 0.0237 | 1.00 | 0.0000 | 0.93 | 0.0255 | 0.86 | 0.0347 | 0.91 | 0.0286 | 0.87 | 0.0336 | 0.93 | 0.0255 | 0.87 | 0.0336 | 0.93 | 0.0255 | 0.88 | 0.0325 | 0.93 | 0.0255 |
| 6 | 1000 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.52 | 0.0500 | 0.88 | 0.0325 | 0.77 | 0.0421 | 0.97 | 0.0171 | 0.91 | 0.0286 | 0.97 | 0.0171 | 0.99 | 0.0099 | 0.88 | 0.0325 | 0.75 | 0.0433 | 0.97 | 0.0171 | 0.83 | 0.0376 | 0.97 | 0.0171 | 0.84 | 0.0367 | 0.97 | 0.0171 | 0.84 | 0.0367 | 0.97 | 0.0171 |
# show table for power
power <- grep("power", names(dat_table), value = FALSE)
knitr::kable(dat_table[,c(1:7,power)], "simple",
col.names = gsub("[.]", " ", names(dat_table[,c(1:7,power)])),
caption = "Table 7. Power and its Monte Carlo Standard Error for each method",
digits = 4, format.args = list(scientific = FALSE))
| scenario | N | p | AUC_0 | r | pm | mech | power AUC CCA | MCE power AUC CCA | power AUC MI2 | MCE power AUC MI2 | power AUC MIB2 | MCE power AUC MIB2 | power AUC HDEL | MCE power AUC HDEL | power AUC KER | MCE power AUC KER | power AUC mice | MCE power AUC mice | power AUC mix | MCE power AUC mix | power AUC AIPW | MCE power AUC AIPW |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 500 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.88 | 0.0325 | 0.85 | 0.0357 | 0.62 | 0.0485 | 0.05 | 0.0218 | 0.79 | 0.0407 | 0.82 | 0.0384 | 0.82 | 0.0384 | 0.77 | 0.0421 |
| 2 | 1000 | 0.1 | 0.85 | 0.5 | 0.3 | MNAR | 0.96 | 0.0196 | 0.92 | 0.0271 | 0.72 | 0.0449 | 0.08 | 0.0271 | 0.87 | 0.0336 | 0.90 | 0.0300 | 0.89 | 0.0313 | 0.87 | 0.0336 |
| 3 | 500 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.98 | 0.0140 | 0.94 | 0.0237 | 0.71 | 0.0454 | 0.06 | 0.0237 | 0.92 | 0.0271 | 0.92 | 0.0271 | 0.93 | 0.0255 | 0.92 | 0.0271 |
| 4 | 1000 | 0.3 | 0.85 | 0.5 | 0.3 | MNAR | 0.97 | 0.0171 | 0.96 | 0.0196 | 0.84 | 0.0367 | 0.10 | 0.0300 | 0.95 | 0.0218 | 0.95 | 0.0218 | 0.95 | 0.0218 | 0.95 | 0.0218 |
| 5 | 500 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.93 | 0.0255 | 0.93 | 0.0255 | 0.69 | 0.0462 | 0.05 | 0.0218 | 0.92 | 0.0271 | 0.88 | 0.0325 | 0.87 | 0.0336 | 0.87 | 0.0336 |
| 6 | 1000 | 0.5 | 0.85 | 0.5 | 0.3 | MNAR | 0.99 | 0.0099 | 0.96 | 0.0196 | 0.85 | 0.0357 | 0.05 | 0.0218 | 0.96 | 0.0196 | 0.98 | 0.0140 | 0.97 | 0.0171 | 0.96 | 0.0196 |
# save results in excel file
write_xlsx(scenario_res, path = "./Analyse/Ergebnisse/res_suppl_mnar.xlsx")
Table 8. Overview of average running time (in seconds) summarized across all scenarios
# table with running time summarized across all scenarios
time <- grep("time", names(dat_table), value = TRUE)
summary(tableby( ~ ., data = dat_table[,c(time)], control = mycontrols), pfootnote = T)
| Overall (N=6) | |
|---|---|
| Average running time for CCA | |
| Mean | 0.009 |
| SD | 0.002 |
| Median (Q1, Q3) | 0.009 (0.007, 0.009) |
| Range | 0.006 - 0.013 |
| Average running time for MI2 | |
| Mean | 0.238 |
| SD | 0.061 |
| Median (Q1, Q3) | 0.222 (0.203, 0.250) |
| Range | 0.179 - 0.351 |
| Average running time for MIB2 | |
| Mean | 1.027 |
| SD | 0.354 |
| Median (Q1, Q3) | 0.943 (0.808, 1.115) |
| Range | 0.677 - 1.662 |
| Average running time for HDEL | |
| Mean | 0.075 |
| SD | 0.012 |
| Median (Q1, Q3) | 0.074 (0.068, 0.079) |
| Range | 0.060 - 0.096 |
| Average running time for KER | |
| Mean | 0.420 |
| SD | 0.249 |
| Median (Q1, Q3) | 0.326 (0.271, 0.619) |
| Range | 0.148 - 0.754 |
| Average running time for mice | |
| Mean | 1.617 |
| SD | 0.261 |
| Median (Q1, Q3) | 1.571 (1.465, 1.776) |
| Range | 1.284 - 2.000 |
| Average running time for mix | |
| Mean | 0.875 |
| SD | 0.194 |
| Median (Q1, Q3) | 0.822 (0.762, 0.927) |
| Range | 0.680 - 1.221 |
| Average running time for AIPW | |
| Mean | 34.401 |
| SD | 19.736 |
| Median (Q1, Q3) | 28.181 (21.044, 51.788) |
| Range | 12.791 - 58.929 |
There are no missing values in the estimation of the AUC
# reshape from wide to long (only one column for bias and estimated AUC, respectively)
performparam <- list(auc_vars,names1)
performnames <- c("AUC","Bias")
dat_fig <- raw_res[,c("scenario","N","p","AUC_0","r","pm","mech",auc_vars,names1)]
dat_fig$id <- seq_along(1:nrow(dat_fig))
dat_long <- reshape(dat_fig, varying=performparam, v.names = performnames, times = methods,
idvar = "id", direction = "long")
dat_long$scenario <- as.factor(dat_long$scenario)
colnames(dat_long)[colnames(dat_long) == "time"] <- "Method" # rename method variable
plot_bias <- ggplot(dat_long, aes(x = Method, y = Bias)) +
geom_violin(fill = colors[1], trim=FALSE) +
stat_summary(fun=mean, geom="point", size=2, color=colors[6]) +
xlab("Method") + ylab("Bias") +
geom_hline(yintercept=0) +
scale_y_continuous(limits = c(-0.15,0.15)) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
facet_grid(N ~ p, labeller = label_both) +
ggtitle("Figure 1. Violin plot of bias") +
theme(axis.title = element_text(size = 18),
axis.text = element_text(size = 16),
plot.title = element_text(size = 20),
strip.text.x = element_text(size = 14),
strip.text.y = element_text(size = 14))
plot_bias
table_b <- dat_long %>%
filter(N==500 & (p==0.1 | p==0.5)) %>%
select(Method, Bias,p) %>%
tbl_strata(strata=p, .tbl_fun = ~ .x %>%
tbl_summary(by=Method,
type = list(all_continuous()~"continuous2"),
statistic = list(all_continuous() ~ c("{mean} ({sd})",
"{median} ({p25}, {p75})",
"[{min}, {max}]")),
digits = list(all_continuous() ~4)))
tab_b <- table_b %>%
as_gt() %>%
tab_header(
title = "Table 9. Summary statistics for bias for a small sample size (N=500)"
)
tab_b
| Table 9. Summary statistics for bias for a small sample size (N=500) | ||||||||||||||||
| Characteristic | 0.1 | 0.5 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AIPW N = 100 |
CCA N = 100 |
HDEL N = 100 |
KER N = 100 |
MI2 N = 100 |
MIB2 N = 100 |
mice N = 100 |
mix N = 100 |
AIPW N = 100 |
CCA N = 100 |
HDEL N = 100 |
KER N = 100 |
MI2 N = 100 |
MIB2 N = 100 |
mice N = 100 |
mix N = 100 |
|
| Bias | ||||||||||||||||
| Mean (SD) | -0.0004 (0.0321) | 0.0085 (0.0328) | 0.0089 (0.0350) | -0.0010 (0.0339) | 0.0024 (0.0343) | 0.0033 (0.0343) | -0.0014 (0.0318) | -0.0017 (0.0324) | 0.0073 (0.0205) | 0.0171 (0.0209) | 0.0187 (0.0224) | 0.0058 (0.0205) | 0.0092 (0.0217) | 0.0100 (0.0224) | 0.0085 (0.0204) | 0.0081 (0.0211) |
| Median (Q1, Q3) | -0.0013 (-0.0202, 0.0205) | 0.0094 (-0.0126, 0.0307) | 0.0123 (-0.0171, 0.0351) | 0.0005 (-0.0233, 0.0208) | 0.0072 (-0.0204, 0.0233) | 0.0069 (-0.0275, 0.0287) | 0.0034 (-0.0242, 0.0201) | 0.0003 (-0.0249, 0.0191) | 0.0086 (-0.0089, 0.0207) | 0.0200 (0.0026, 0.0306) | 0.0173 (0.0034, 0.0362) | 0.0073 (-0.0102, 0.0200) | 0.0111 (-0.0088, 0.0248) | 0.0121 (-0.0053, 0.0281) | 0.0115 (-0.0064, 0.0219) | 0.0102 (-0.0071, 0.0214) |
| [Min, Max] | [-0.0780, 0.0830] | [-0.0873, 0.0828] | [-0.0724, 0.0969] | [-0.0805, 0.0838] | [-0.0817, 0.0899] | [-0.0723, 0.0888] | [-0.0899, 0.0781] | [-0.0789, 0.0806] | [-0.0456, 0.0496] | [-0.0327, 0.0638] | [-0.0403, 0.0689] | [-0.0486, 0.0470] | [-0.0453, 0.0506] | [-0.0482, 0.0564] | [-0.0409, 0.0567] | [-0.0453, 0.0508] |
# reshape summary results for further plots
performparam <- list(names1,names2,names3,names4,names13,names5,names6,names7,names8,names9,names14,names10,names11)
performnames <- c("Bias","RMSE","empirical_SE","Coverage","be_coverage",
"Power","MCE_bias","MCE_MSE","MCE_empSE","MCE_cov", "MCE_be_cov", "MCE_power", "av_time")
scenario_res$id <- seq_along(1:nrow(scenario_res))
res_long <- reshape(scenario_res, varying=performparam, v.names = performnames, times = methods,
idvar = "id", direction = "long")
colnames(res_long)[colnames(res_long) == "time"] <- "Method" # rename method variable
Comparison between additional MNAR scenarios (type=MID) and main simulation MNAR scenarios (type=RIGHT)
load("./Analyse/mnar_test.RData")
mnar_test$type <- "RIGHT"
res_long$type <- "MID"
mnar_dta <- rbind(res_long, mnar_test)
comp_bias <- ggplot(mnar_dta, aes(x = p, y = Bias, group = Method)) +
geom_line(aes(color=Method, linetype = Method), linewidth=1) +
scale_color_manual(values = colors) +
xlab("Prevalence") + ylab("Bias") +
facet_grid(N ~ type, labeller = label_both) +
scale_x_continuous(breaks = c(0.1,0.3,0.5)) +
ggtitle("Figure 2. Bias for MNAR type=mid vs. type=right (pm=0.3, r=0.5, true AUC=0.85)") +
theme(axis.title = element_text(size = 18),
axis.text = element_text(size = 16),
plot.title = element_text(size = 20),
strip.text.x = element_text(size = 14),
strip.text.y = element_text(size = 14))
comp_bias
All methods tend to overestimate the AUC under type=MID whereas they tend to underestimate the AUC under type=RIGHT. Additionally, the bias increases with higher prevalence given type=MID while it stays the same or slightly decreases with higher prevalence given type=RIGHT.
Comparison between additional MNAR scenarios (type=MID) and main simulation MNAR scenarios (type=RIGHT)
comp_rmse <- ggplot(mnar_dta, aes(x = p, y = RMSE, group = Method)) +
geom_line(aes(color=Method, linetype = Method), linewidth=1) +
scale_color_manual(values = colors) +
xlab("Prevalence") + ylab("Root mean squared error") +
facet_grid(N ~ type, labeller = label_both) +
scale_x_continuous(breaks = c(0.1,0.3,0.5)) +
ggtitle("Figure 3. RMSE for MNAR type=mid vs. type=right (pm=0.3, r=0.5, true AUC=0.85)") +
theme(axis.title = element_text(size = 18),
axis.text = element_text(size = 16),
plot.title = element_text(size = 20),
strip.text.x = element_text(size = 14),
strip.text.y = element_text(size = 14))
comp_rmse
Regardless of method, the RMSE is higher for type=RIGHT than for type=MID if the prevalence of the target condition is low. However, there are no differences in RMSE between type=RIGHT and type=MID with higher prevalence.
# calculate 95% Monte carlo CI for coverage
res_long$MC_cov_ciu <- res_long$Coverage+1.96*res_long$MCE_cov
res_long$MC_cov_cil <- res_long$Coverage-1.96*res_long$MCE_cov
# variable indicating whether bias is "too high" (bias>5%)
res_long$rel_bias <- (res_long$Bias/res_long$AUC_0)*100 # relative bias in %
res_long$bias_cut <- as.factor(if_else(res_long$rel_bias>=5 | res_long$rel_bias<=(-5), "too biased (>=5%)", "acceptable biased"))
plot_conv <- ggplot(res_long, aes(y=Method, x=Coverage, color=bias_cut)) +
geom_segment( aes(y=Method, yend=Method, x=0.95, xend=Coverage)) +
geom_point(size=2) +
geom_vline(xintercept=0.95) +
geom_text(aes(MC_cov_ciu, Method, label = ")")) +
geom_text(aes(MC_cov_cil, Method, label = "(")) +
facet_grid(N ~ p, labeller = label_both) + # pm~p
scale_color_grey() +
ggtitle("Figure 4. Coverage probability") +
labs(color="Bias categorized") +
theme(axis.title = element_text(size = 18),
axis.text = element_text(size = 16),
plot.title = element_text(size = 20),
strip.text.x = element_text(size = 14),
strip.text.y = element_text(size = 14),
legend.position = "bottom")
plot_conv
plot_power <- ggplot(res_long, aes(x = p, y = Power, group = Method)) +
geom_line(aes(color=Method, linetype=Method), linewidth=1) +
scale_x_continuous(breaks = c(0.1,0.3,0.5)) +
scale_color_manual(values = colors) +
xlab("Proportion of missing values") + ylab("Power") +
facet_grid( ~ N, labeller = label_both) +
ggtitle("Figure 5. Power") +
theme(axis.title = element_text(size = 18),
axis.text = element_text(size = 16),
plot.title = element_text(size = 20),
strip.text.x = element_text(size = 14),
strip.text.y = element_text(size = 14))
plot_power
Table 10. Summary statistics of Monte Carlo Standard Errors summarized across all scenarios and iterations
summary(tableby(Method ~ ., data = res_long[,c("Method", "MCE_bias","MCE_MSE", "MCE_cov", "MCE_power")], control = mycontrols), pfootnote = T)
| AIPW (N=6) | CCA (N=6) | HDEL (N=6) | KER (N=6) | MI2 (N=6) | MIB2 (N=6) | mice (N=6) | mix (N=6) | Total (N=48) | |
|---|---|---|---|---|---|---|---|---|---|
| MCE_bias | |||||||||
| Mean | 0.002 | 0.002 | 0.002 | 0.002 | 0.002 | 0.002 | 0.002 | 0.002 | 0.002 |
| SD | 0.001 | 0.001 | 0.001 | 0.001 | 0.001 | 0.001 | 0.001 | 0.001 | 0.001 |
| Median (Q1, Q3) | 0.002 (0.002, 0.002) | 0.002 (0.001, 0.002) | 0.002 (0.002, 0.002) | 0.002 (0.002, 0.002) | 0.002 (0.002, 0.002) | 0.002 (0.002, 0.002) | 0.002 (0.002, 0.002) | 0.002 (0.002, 0.002) | 0.002 (0.001, 0.002) |
| Range | 0.001 - 0.003 | 0.001 - 0.003 | 0.001 - 0.004 | 0.001 - 0.003 | 0.001 - 0.003 | 0.001 - 0.003 | 0.001 - 0.003 | 0.001 - 0.003 | 0.001 - 0.004 |
| MCE_MSE | |||||||||
| Mean | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
| SD | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
| Median (Q1, Q3) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) | 0.000 (0.000, 0.000) |
| Range | 0.000 - 0.000 | 0.000 - 0.000 | 0.000 - 0.000 | 0.000 - 0.000 | 0.000 - 0.000 | 0.000 - 0.000 | 0.000 - 0.000 | 0.000 - 0.000 | 0.000 - 0.000 |
| MCE_cov | |||||||||
| Mean | 0.030 | 0.039 | 0.007 | 0.029 | 0.036 | 0.021 | 0.029 | 0.029 | 0.027 |
| SD | 0.005 | 0.008 | 0.006 | 0.009 | 0.003 | 0.004 | 0.006 | 0.006 | 0.011 |
| Median (Q1, Q3) | 0.031 (0.027, 0.032) | 0.039 (0.033, 0.045) | 0.010 (0.002, 0.010) | 0.028 (0.022, 0.034) | 0.036 (0.034, 0.038) | 0.020 (0.018, 0.021) | 0.029 (0.025, 0.033) | 0.028 (0.024, 0.033) | 0.030 (0.022, 0.035) |
| Range | 0.022 - 0.037 | 0.030 - 0.050 | 0.000 - 0.014 | 0.020 - 0.043 | 0.032 - 0.042 | 0.017 - 0.029 | 0.022 - 0.038 | 0.022 - 0.037 | 0.000 - 0.050 |
| MCE_power | |||||||||
| Mean | 0.030 | 0.020 | 0.024 | 0.028 | 0.025 | 0.043 | 0.027 | 0.028 | 0.028 |
| SD | 0.008 | 0.008 | 0.003 | 0.008 | 0.006 | 0.005 | 0.009 | 0.008 | 0.009 |
| Median (Q1, Q3) | 0.030 (0.023, 0.034) | 0.018 (0.015, 0.024) | 0.023 (0.022, 0.026) | 0.027 (0.023, 0.032) | 0.025 (0.021, 0.027) | 0.045 (0.039, 0.046) | 0.029 (0.023, 0.032) | 0.028 (0.023, 0.033) | 0.027 (0.022, 0.034) |
| Range | 0.020 - 0.042 | 0.010 - 0.032 | 0.022 - 0.030 | 0.020 - 0.041 | 0.020 - 0.036 | 0.036 - 0.049 | 0.014 - 0.038 | 0.017 - 0.038 | 0.010 - 0.049 |
Figure 6. Nested loop plot for bias
s1 <- simsum(data = dat_long, estvarname = "AUC", ref="CCA", true = "AUC_0", methodvar = "Method", by=c("p", "N"))
#summary(s1)
ap <- autoplot(s1, type = "nlp", stats = "bias")
ap + scale_color_manual(values = colors)
#autoplot(s1, type = "nlp", stats = "mse")
Bianco AM, Boente G, González–Manteiga W, Pérez–González A. Estimators for ROC curves with missing biomarkers values and informative covariates. Statistical Methods & Applications. 2023.
Long Q, Zhang X, Hsu C-H. Nonparametric multiple imputation for receiver operating characteristics analysis when some biomarker values are missing at random. Stat Med. 2011a;30(26):3149-61.
Long Q, Zhang X, Johnson BA. Robust estimation of area under ROC curve using auxiliary variables in the presence of missing biomarker values. Biometrics. 2011b;67(2):559-67.
Schafer J. mix: Estimation/Multiple Imputation for Mixed Categorical and Continuous Data. R package version 10-11. 2022.
van Buuren S, Groothuis-Oudshoorn K. mice: Multivariate Imputation by Chained Equations in R. Journal of Statistical Software. 2011;45(3):1 - 67.
van Smeden M, Moons KG, de Groot JA, et al. Sample size for binary logistic prediction models: Beyond events per variable criteria. Stat Methods Med Res. 2019;28(8):2455-2474. doi:10.1177/0962280218784726
Wang B, Qin G. Imputation-based empirical likelihood inference for the area under the ROC curve with missing data. Stat Interface. 2012;5(3):319-29.
Wang B, Qin G. Empirical likelihood-based confidence intervals for the sensitivity of a continuous-scale diagnostic test with missing data. Commun Stat Theory Methods. 2014;43(15):3248-68.
sessioninfo::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
## setting value
## version R version 4.4.1 (2024-06-14 ucrt)
## os Windows 10 x64 (build 19045)
## system x86_64, mingw32
## ui RTerm
## language (EN)
## collate German_Germany.utf8
## ctype German_Germany.utf8
## tz Europe/Berlin
## date 2025-04-25
## pandoc 3.2 @ C:/Program Files/RStudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)
##
## ─ Packages ───────────────────────────────────────────────────────────────────
## package * version date (UTC) lib source
## abind 1.4-8 2024-09-12 [1] CRAN (R 4.4.1)
## arsenal * 3.6.3 2021-06-04 [1] CRAN (R 4.4.1)
## backports 1.5.0 2024-05-23 [1] CRAN (R 4.4.0)
## broom 1.0.6 2024-05-17 [1] CRAN (R 4.4.1)
## bslib 0.8.0 2024-07-29 [1] CRAN (R 4.4.1)
## cachem 1.1.0 2024-05-16 [1] CRAN (R 4.4.1)
## car 3.1-2 2023-03-30 [1] CRAN (R 4.4.1)
## carData 3.0-5 2022-01-06 [1] CRAN (R 4.4.1)
## cards 0.2.2 2024-09-02 [1] CRAN (R 4.4.1)
## checkmate 2.3.2 2024-07-29 [1] CRAN (R 4.4.1)
## cli 3.6.3 2024-06-21 [1] CRAN (R 4.4.1)
## colorspace 2.1-1 2024-07-26 [1] CRAN (R 4.4.1)
## commonmark 1.9.1 2024-01-30 [1] CRAN (R 4.4.1)
## digest 0.6.37 2024-08-19 [1] CRAN (R 4.4.1)
## dplyr * 1.1.4 2023-11-17 [1] CRAN (R 4.4.1)
## evaluate 1.0.3 2025-01-10 [1] CRAN (R 4.4.3)
## fansi 1.0.6 2023-12-08 [1] CRAN (R 4.4.1)
## farver 2.1.2 2024-05-13 [1] CRAN (R 4.4.1)
## fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.4.1)
## generics 0.1.3 2022-07-05 [1] CRAN (R 4.4.1)
## ggplot2 * 3.5.1 2024-04-23 [1] CRAN (R 4.4.1)
## ggpubr * 0.6.0 2023-02-10 [1] CRAN (R 4.4.1)
## ggridges 0.5.6 2024-01-23 [1] CRAN (R 4.4.1)
## ggsignif 0.6.4 2022-10-13 [1] CRAN (R 4.4.1)
## glue 1.7.0 2024-01-09 [1] CRAN (R 4.4.1)
## gt * 0.11.0 2024-07-09 [1] CRAN (R 4.4.1)
## gtable 0.3.5 2024-04-22 [1] CRAN (R 4.4.1)
## gtsummary * 2.0.2 2024-09-05 [1] CRAN (R 4.4.1)
## highr 0.11 2024-05-26 [1] CRAN (R 4.4.1)
## htmltools 0.5.8.1 2024-04-04 [1] CRAN (R 4.4.1)
## insight 0.20.4 2024-09-01 [1] CRAN (R 4.4.1)
## jquerylib 0.1.4 2021-04-26 [1] CRAN (R 4.4.1)
## jsonlite 1.8.8 2023-12-04 [1] CRAN (R 4.4.1)
## knitr 1.48 2024-07-07 [1] CRAN (R 4.4.1)
## labeling 0.4.3 2023-08-29 [1] CRAN (R 4.4.0)
## lifecycle 1.0.4 2023-11-07 [1] CRAN (R 4.4.1)
## magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.4.1)
## markdown 1.13 2024-06-04 [1] CRAN (R 4.4.1)
## munsell 0.5.1 2024-04-01 [1] CRAN (R 4.4.1)
## pillar 1.9.0 2023-03-22 [1] CRAN (R 4.4.1)
## pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.4.1)
## purrr 1.0.2 2023-08-10 [1] CRAN (R 4.4.1)
## R6 2.5.1 2021-08-19 [1] CRAN (R 4.4.1)
## RColorBrewer * 1.1-3 2022-04-03 [1] CRAN (R 4.4.0)
## rlang 1.1.4 2024-06-04 [1] CRAN (R 4.4.1)
## rmarkdown 2.28 2024-08-17 [1] CRAN (R 4.4.1)
## rprojroot 2.0.4 2023-11-05 [1] CRAN (R 4.4.2)
## rsimsum * 0.13.0 2024-03-03 [1] CRAN (R 4.4.1)
## rstatix 0.7.2 2023-02-01 [1] CRAN (R 4.4.1)
## rstudioapi 0.16.0 2024-03-24 [1] CRAN (R 4.4.1)
## sass 0.4.9 2024-03-15 [1] CRAN (R 4.4.1)
## scales 1.3.0 2023-11-28 [1] CRAN (R 4.4.1)
## sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.4.1)
## sjlabelled 1.2.0 2022-04-10 [1] CRAN (R 4.4.1)
## tibble 3.2.1 2023-03-20 [1] CRAN (R 4.4.1)
## tidyr 1.3.1 2024-01-24 [1] CRAN (R 4.4.1)
## tidyselect 1.2.1 2024-03-11 [1] CRAN (R 4.4.1)
## utf8 1.2.4 2023-10-22 [1] CRAN (R 4.4.1)
## vctrs 0.6.5 2023-12-01 [1] CRAN (R 4.4.1)
## withr 3.0.2 2024-10-28 [1] CRAN (R 4.4.3)
## writexl * 1.5.0 2024-02-09 [1] CRAN (R 4.4.1)
## xfun 0.47 2024-08-17 [1] CRAN (R 4.4.1)
## xml2 1.3.6 2023-12-04 [1] CRAN (R 4.4.1)
## yaml 2.3.10 2024-07-26 [1] CRAN (R 4.4.1)
##
## [1] C:/Users/stahlmann/AppData/Local/R/win-library/4.4
## [2] C:/Program Files/R/R-4.4.1/library
##
## ──────────────────────────────────────────────────────────────────────────────