--- title: "Validation of bbssr Package Functions" author: "Gosuke Homma" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: toc: true toc_depth: 3 vignette: > %\VignetteIndexEntry{Validation of bbssr Package Functions} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 8, fig.height = 6, fig.align = "center", warning = FALSE, message = FALSE ) # Load required packages # Note: These packages must be installed separately before building this vignette library(bbssr) # Check if optional packages are available required_packages <- c("dplyr", "ggplot2", "tidyr", "microbenchmark") for (pkg in required_packages) { if (!requireNamespace(pkg, quietly = TRUE)) { message(paste("Package", pkg, "not available. Install with: install.packages('", pkg, "')", sep = "")) } else { library(pkg, character.only = TRUE) } } # Load base packages explicitly library(stats) library(utils) library(base) # Check if validation packages are available has_exact <- requireNamespace("Exact", quietly = TRUE) has_exact2x2 <- requireNamespace("exact2x2", quietly = TRUE) if (!has_exact) { message("Note: Exact package not available. Install with: install.packages('Exact')") } else { library(Exact) } if (!has_exact2x2) { message("Note: exact2x2 package not available. Install with: install.packages('exact2x2')") } else { library(exact2x2) } if (!has_exact || !has_exact2x2) { knitr::opts_chunk$set(eval = FALSE) warning("Validation packages not available. Code will not be evaluated.") } ``` ## Introduction This vignette validates the `BinaryPower()` and `BinarySampleSize()` functions in the `bbssr` package by comparing results with established R packages: `Exact` and `exact2x2`. We also compare computational performance to demonstrate the efficiency improvements in `bbssr`. The validation covers all five statistical tests implemented in `bbssr`: 1. Pearson chi-squared test (`'Chisq'`) 2. Fisher exact test (`'Fisher'`) 3. Fisher mid-p test (`'Fisher-midP'`) 4. Z-pooled exact unconditional test (`'Z-pool'`) 5. Boschloo exact unconditional test (`'Boschloo'`) ```{r load_packages, eval=has_exact && has_exact2x2} # Load external validation packages library(Exact) library(exact2x2) ``` ```{r load_bbssr_only, eval=!has_exact || !has_exact2x2} # If external packages are not available, just load bbssr library(bbssr) ``` ## Validation of BinaryPower Function ### Test Parameters We use the following parameters for validation: ```{r validation_parameters} # Test parameters for validation p1 <- c(0.5, 0.6, 0.7, 0.8) # Response rates in treatment group p2 <- c(0.2, 0.2, 0.2, 0.2) # Response rates in control group N1 <- 10 # Sample size in treatment group N2 <- 40 # Sample size in control group alpha <- 0.025 # One-sided significance level ``` ## Quick Verification Example For users who want to see immediate results without running external packages: ```{r quick_verification} # Quick verification using bbssr only cat("=== Quick Verification Results ===\n") cat("Test Parameters:\n") cat("p1 =", paste(p1, collapse = ", "), "\n") cat("p2 =", paste(p2, collapse = ", "), "\n") cat("N1 =", N1, ", N2 =", N2, ", alpha =", alpha, "\n\n") # Show all test results tests <- c('Chisq', 'Fisher', 'Fisher-midP', 'Z-pool', 'Boschloo') for(test in tests) { powers <- BinaryPower(p1, p2, N1, N2, alpha, Test = test) cat(sprintf("%-12s: %s\n", test, paste(round(powers, 6), collapse = " "))) } ``` ### 1. Pearson Chi-squared Test ```{r chisq_validation, eval=has_exact && has_exact2x2} # bbssr results bbssr_chisq <- BinaryPower(p1, p2, N1, N2, alpha, Test = 'Chisq') print("bbssr results:") print(round(bbssr_chisq, 7)) # Exact package results for comparison exact_chisq <- sapply(seq(p1), function(i) { Exact::power.exact.test(p1[i], p2[i], N1, N2, method = 'pearson chisq', 'greater', alpha)$power }) print("Exact package results:") print(round(exact_chisq, 7)) # Create comparison table chisq_comparison <- data.frame( p1 = p1, p2 = p2, bbssr = round(bbssr_chisq, 7), Exact = round(exact_chisq, 7), Difference = round(abs(bbssr_chisq - exact_chisq), 10) ) knitr::kable(chisq_comparison, caption = "Pearson Chi-squared Test: bbssr vs Exact Package") ``` ### 2. Fisher Exact Test ```{r fisher_validation, eval=has_exact && has_exact2x2} # bbssr results bbssr_fisher <- BinaryPower(p1, p2, N1, N2, alpha, Test = 'Fisher') # Exact package results for comparison exact_fisher <- sapply(seq(p1), function(i) { Exact::power.exact.test(p1[i], p2[i], N1, N2, method = 'fisher', 'greater', alpha)$power }) # Create comparison table fisher_comparison <- data.frame( p1 = p1, p2 = p2, bbssr = round(bbssr_fisher, 7), Exact = round(exact_fisher, 7), Difference = round(abs(bbssr_fisher - exact_fisher), 10) ) knitr::kable(fisher_comparison, caption = "Fisher Exact Test: bbssr vs Exact Package") ``` ### 3. Fisher Mid-p Test ```{r fisher_midp_validation, eval=has_exact && has_exact2x2} # bbssr results bbssr_midp <- BinaryPower(p1, p2, N1, N2, alpha, Test = 'Fisher-midP') # exact2x2 package results for comparison exact2x2_midp <- sapply(seq(p1), function(i) { exact2x2::Power2x2(N1, N2, p1[i], p2[i], alpha, pvalFunc = function(x1, n1, x2, n2) { fisher.exact(matrix(c(x1, n1 - x1, x2, n2 - x2), 2), alt = 'greater', midp = TRUE)$p.value } ) }) # Create comparison table midp_comparison <- data.frame( p1 = p1, p2 = p2, bbssr = round(bbssr_midp, 7), exact2x2 = round(exact2x2_midp, 7), Difference = round(abs(bbssr_midp - exact2x2_midp), 10) ) knitr::kable(midp_comparison, caption = "Fisher Mid-p Test: bbssr vs exact2x2 Package") ``` ### 4. Z-pooled Exact Unconditional Test ```{r zpool_validation, eval=has_exact && has_exact2x2} # bbssr results bbssr_zpool <- BinaryPower(p1, p2, N1, N2, alpha, Test = 'Z-pool') # Exact package results for comparison exact_zpool <- sapply(seq(p1), function(i) { Exact::power.exact.test(p1[i], p2[i], N1, N2, method = 'z-pooled', 'greater', alpha)$power }) # Create comparison table zpool_comparison <- data.frame( p1 = p1, p2 = p2, bbssr = round(bbssr_zpool, 7), Exact = round(exact_zpool, 7), Difference = round(abs(bbssr_zpool - exact_zpool), 10) ) knitr::kable(zpool_comparison, caption = "Z-pooled Test: bbssr vs Exact Package") ``` ### 5. Boschloo Exact Unconditional Test ```{r boschloo_validation, eval=has_exact && has_exact2x2} # bbssr results bbssr_boschloo <- BinaryPower(p1, p2, N1, N2, alpha, Test = 'Boschloo') # Exact package results for comparison exact_boschloo <- sapply(seq(p1), function(i) { Exact::power.exact.test(p1[i], p2[i], N1, N2, method = 'boschloo', 'greater', alpha)$power }) # Create comparison table boschloo_comparison <- data.frame( p1 = p1, p2 = p2, bbssr = round(bbssr_boschloo, 7), Exact = round(exact_boschloo, 7), Difference = round(abs(bbssr_boschloo - exact_boschloo), 10) ) knitr::kable(boschloo_comparison, caption = "Boschloo Test: bbssr vs Exact Package") ``` ## Performance Comparison ### Enhanced Computational Speed Benchmarks We compare the computational speed using more demanding scenarios to highlight bbssr's performance advantages. ```{r performance_setup} # Enhanced parameters for performance comparison perf_scenarios <- expand.grid( p1 = c(0.5, 0.6, 0.7, 0.8), p2 = c(0.2, 0.3, 0.4), N1 = c(15, 20, 25), N2 = c(15, 20, 25) ) %>% filter(p1 > p2) %>% # Only meaningful comparisons slice_head(n = 8) # Select representative scenarios perf_alpha <- 0.025 # Display scenarios for transparency knitr::kable(perf_scenarios, caption = "Performance Benchmark Scenarios") ``` ### BinaryPower Performance Comparison ```{r power_performance, eval=has_exact && has_exact2x2} # Function to benchmark a single scenario benchmark_scenario <- function(p1, p2, N1, N2) { microbenchmark::microbenchmark( bbssr_chisq = BinaryPower(p1, p2, N1, N2, perf_alpha, Test = 'Chisq'), exact_chisq = Exact::power.exact.test(p1, p2, N1, N2, method = 'pearson chisq', 'greater', perf_alpha), bbssr_fisher = BinaryPower(p1, p2, N1, N2, perf_alpha, Test = 'Fisher'), exact_fisher = Exact::power.exact.test(p1, p2, N1, N2, method = 'fisher', 'greater', perf_alpha), bbssr_zpool = BinaryPower(p1, p2, N1, N2, perf_alpha, Test = 'Z-pool'), exact_zpool = Exact::power.exact.test(p1, p2, N1, N2, method = 'z-pooled', 'greater', perf_alpha), bbssr_boschloo = BinaryPower(p1, p2, N1, N2, perf_alpha, Test = 'Boschloo'), exact_boschloo = Exact::power.exact.test(p1, p2, N1, N2, method = 'boschloo', 'greater', perf_alpha), times = 20 ) } # Run benchmarks for multiple scenarios benchmark_results <- list() for(i in 1:nrow(perf_scenarios)) { scenario <- perf_scenarios[i, ] cat(sprintf("Benchmarking scenario %d: p1=%.1f, p2=%.1f, N1=%d, N2=%d\n", i, scenario$p1, scenario$p2, scenario$N1, scenario$N2)) benchmark_results[[i]] <- benchmark_scenario( scenario$p1, scenario$p2, scenario$N1, scenario$N2 ) %>% summary() %>% mutate( scenario_id = i, p1 = scenario$p1, p2 = scenario$p2, N1 = scenario$N1, N2 = scenario$N2, total_n = scenario$N1 + scenario$N2 ) } # Combine all benchmark results all_benchmarks <- do.call(rbind, benchmark_results) # Calculate speed improvements speed_comparison <- all_benchmarks %>% mutate( test_name = case_when( grepl("chisq", expr) ~ "Chi-squared", grepl("fisher", expr) & !grepl("zpool|boschloo", expr) ~ "Fisher", grepl("zpool", expr) ~ "Z-pooled", grepl("boschloo", expr) ~ "Boschloo" ), package = if_else(grepl("bbssr", expr), "bbssr", "Exact") ) %>% group_by(scenario_id, test_name, package, p1, p2, N1, N2, total_n) %>% summarise(median_time = median(median), .groups = 'drop') %>% tidyr::pivot_wider(names_from = package, values_from = median_time) %>% mutate( speed_improvement = round(Exact / bbssr, 1), bbssr_ms = round(bbssr / 1000, 2), exact_ms = round(Exact / 1000, 2) ) # Display summary speed_summary <- speed_comparison %>% group_by(test_name) %>% summarise( avg_improvement = round(mean(speed_improvement), 1), max_improvement = round(max(speed_improvement), 1), min_improvement = round(min(speed_improvement), 1), .groups = 'drop' ) knitr::kable(speed_summary, col.names = c("Test", "Avg Speed-up", "Max Speed-up", "Min Speed-up"), caption = "Speed Improvement Summary: bbssr vs Exact Package (times faster)") ``` ### Performance Visualization ```{r performance_plot, eval=has_exact && has_exact2x2, fig.width=8, fig.height=10, out.width="100%"} # Create speed improvement comparison (how many times faster bbssr is) speed_plot_data <- speed_comparison %>% mutate( test_name = factor(test_name, levels = c("Chi-squared", "Fisher", "Z-pooled", "Boschloo")), scenario_label = paste0("Scenario ", scenario_id, "\n(N=", total_n, ")") ) # Speed improvement plot speed_plot <- ggplot(speed_plot_data, aes(x = scenario_label, y = speed_improvement)) + geom_col(fill = "#4CAF50", alpha = 0.8, width = 0.6) + geom_text(aes(label = paste0(speed_improvement, "x")), vjust = -0.3, size = 3, fontface = "bold") + facet_wrap(~test_name, ncol = 1, scales = "free_y") + geom_hline(yintercept = 1, linetype = "dashed", color = "red", linewidth = 1) + scale_y_continuous(expand = expansion(mult = c(0, 0.15))) + # Add 15% padding at top labs( title = "Speed Improvement: bbssr vs Exact Package", subtitle = "How many times faster bbssr is compared to Exact package", x = "Benchmark Scenario", y = "Speed Improvement Factor (times faster)", caption = "Red dashed line shows no improvement (factor = 1). Higher bars = better performance." ) + theme_minimal() + theme( plot.title = element_text(size = 14, hjust = 0.5, margin = margin(b = 5)), plot.subtitle = element_text(size = 11, hjust = 0.5, margin = margin(b = 15)), strip.text = element_text(size = 12, face = "bold", margin = margin(t = 8, b = 8)), strip.background = element_rect(fill = "gray95", color = "gray80"), axis.title.x = element_text(size = 11, margin = margin(t = 10)), axis.title.y = element_text(size = 11, margin = margin(r = 10)), axis.text.x = element_text(size = 8, angle = 45, hjust = 1), axis.text.y = element_text(size = 9), panel.grid.minor.x = element_blank(), panel.grid.major.x = element_blank(), plot.margin = margin(t = 10, r = 10, b = 15, l = 10) ) print(speed_plot) # Detailed execution time comparison time_comparison_data <- speed_comparison %>% select(scenario_id, test_name, bbssr_ms, exact_ms, total_n) %>% tidyr::pivot_longer( cols = c(bbssr_ms, exact_ms), names_to = "package", values_to = "time_ms" ) %>% mutate( package = case_when( package == "bbssr_ms" ~ "bbssr", package == "exact_ms" ~ "Exact" ), test_name = factor(test_name, levels = c("Chi-squared", "Fisher", "Z-pooled", "Boschloo")), scenario_label = paste0("Scenario ", scenario_id, "\n(N=", total_n, ")") ) # Execution time plot time_plot <- ggplot(time_comparison_data, aes(x = scenario_label, y = time_ms, fill = package)) + geom_col(position = "dodge", width = 0.7) + facet_wrap(~test_name, ncol = 1, scales = "free_y") + scale_fill_manual( values = c("bbssr" = "#2E8B57", "Exact" = "#CD5C5C"), name = "Package" ) + labs( title = "Execution Time Comparison: bbssr vs Exact Package", subtitle = "Actual execution times in milliseconds", x = "Benchmark Scenario", y = "Execution Time (milliseconds)", caption = "Lower bars indicate better performance" ) + theme_minimal() + theme( plot.title = element_text(size = 14, hjust = 0.5, margin = margin(b = 5)), plot.subtitle = element_text(size = 11, hjust = 0.5, margin = margin(b = 15)), strip.text = element_text(size = 12, face = "bold", margin = margin(t = 8, b = 8)), strip.background = element_rect(fill = "gray95", color = "gray80"), legend.position = "bottom", legend.title = element_text(size = 11), legend.text = element_text(size = 10), axis.title.x = element_text(size = 11, margin = margin(t = 10)), axis.title.y = element_text(size = 11, margin = margin(r = 10)), axis.text.x = element_text(size = 8, angle = 45, hjust = 1), axis.text.y = element_text(size = 9), panel.grid.minor.x = element_blank(), panel.grid.major.x = element_blank(), plot.margin = margin(t = 10, r = 10, b = 15, l = 10) ) print(time_plot) ``` ### Speed Improvement Summary ```{r speed_improvement_summary, eval=has_exact && has_exact2x2} # Overall performance summary overall_summary <- speed_comparison %>% summarise( total_scenarios = n(), overall_avg_improvement = round(mean(speed_improvement), 1), overall_max_improvement = round(max(speed_improvement), 1), overall_min_improvement = round(min(speed_improvement), 1), scenarios_over_2x = sum(speed_improvement >= 2), scenarios_over_5x = sum(speed_improvement >= 5), scenarios_over_10x = sum(speed_improvement >= 10) ) cat("Performance Summary:\n") cat(sprintf("- Total benchmark scenarios: %d\n", overall_summary$total_scenarios)) cat(sprintf("- Average speed improvement: %.1fx faster\n", overall_summary$overall_avg_improvement)) cat(sprintf("- Maximum speed improvement: %.1fx faster\n", overall_summary$overall_max_improvement)) cat(sprintf("- Minimum speed improvement: %.1fx faster\n", overall_summary$overall_min_improvement)) cat(sprintf("- Scenarios where bbssr is >2x faster: %d (%.1f%%)\n", overall_summary$scenarios_over_2x, 100 * overall_summary$scenarios_over_2x / overall_summary$total_scenarios)) cat(sprintf("- Scenarios where bbssr is >5x faster: %d (%.1f%%)\n", overall_summary$scenarios_over_5x, 100 * overall_summary$scenarios_over_5x / overall_summary$total_scenarios)) cat(sprintf("- Scenarios where bbssr is >10x faster: %d (%.1f%%)\n", overall_summary$scenarios_over_10x, 100 * overall_summary$scenarios_over_10x / overall_summary$total_scenarios)) ``` ## Summary of Validation Results ### Accuracy Validation The validation results demonstrate that `bbssr` functions produce **identical results** to established packages: - **BinaryPower()**: All five statistical tests show perfect agreement with `Exact` and `exact2x2` packages - **Numerical Precision**: Differences are within machine precision (< 1e-10) ### Performance Improvements The `bbssr` package demonstrates significant computational efficiency across all statistical tests. ### Key Advantages of bbssr 1. **Computational Efficiency**: Significantly faster execution times across all statistical tests 2. **Numerical Accuracy**: Identical results to established packages with robust implementation 3. **Comprehensive Functionality**: Unified interface for multiple exact tests and BSSR methodology 4. **Optimized Implementation**: Efficient algorithms designed for clinical trial applications ## Conclusion The validation results confirm that `bbssr` provides: - **Accurate calculations** identical to established packages - **Superior performance** with substantial speed improvements - **Reliable implementation** suitable for production use in clinical trials The package successfully combines statistical rigor with computational efficiency, making it an excellent choice for implementing blinded sample size re-estimation in clinical trials with binary endpoints. ## Session Information ```{r session_info} sessionInfo() ```