inst/doc/result_formatting_vignette.R

## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)

# Check package availability
ggplot2_available <- requireNamespace("ggplot2", quietly = TRUE)

## ----setup--------------------------------------------------------------------
library(boinet)
library(dplyr)

# Load ggplot2 if available
if (requireNamespace("ggplot2", quietly = TRUE)) {
  library(ggplot2)
}

## ----simulation, eval=FALSE---------------------------------------------------
# # Example TITE-BOIN-ET simulation
# result <- tite.boinet(
#   n.dose = 5,
#   start.dose = 1,
#   size.cohort = 3,
#   n.cohort = 15,
#   toxprob = c(0.02, 0.08, 0.15, 0.25, 0.40),
#   effprob = c(0.10, 0.20, 0.35, 0.50, 0.65),
#   phi = 0.30,
#   delta = 0.60,
#   tau.T = 28,
#   tau.E = 42,
#   accrual = 7,
#   estpt.method = "obs.prob",
#   obd.method = "max.effprob",
#   n.sim = 1000
# )

## ----mock_result, echo=FALSE--------------------------------------------------
# Create mock result for demonstration
result <- list(
  toxprob = c("1" = 0.02, "2" = 0.08, "3" = 0.15, "4" = 0.25, "5" = 0.40),
  effprob = c("1" = 0.10, "2" = 0.20, "3" = 0.35, "4" = 0.50, "5" = 0.65),
  n.patient = c("1" = 8.2, "2" = 12.5, "3" = 15.8, "4" = 10.3, "5" = 7.2),
  prop.select = c("1" = 5.2, "2" = 18.7, "3" = 42.1, "4" = 28.3, "5" = 5.7),
  phi = 0.30,
  delta = 0.60,
  lambda1 = 0.03,
  lambda2 = 0.42,
  eta1 = 0.36,
  tau.T = 28,
  tau.E = 42,
  accrual = 7,
  duration = 156.3,
  prop.stop = 3.2,
  n.sim = 1000
)
class(result) <- "tite.boinet"

## ----manual_extraction--------------------------------------------------------
# Extract operating characteristics manually
extract_oc_data <- function(boinet_result) {
  dose_levels <- names(boinet_result$n.patient)
  
  data.frame(
    dose_level = dose_levels,
    toxicity_prob = as.numeric(boinet_result$toxprob),
    efficacy_prob = as.numeric(boinet_result$effprob),
    n_patients = as.numeric(boinet_result$n.patient),
    selection_prob = as.numeric(boinet_result$prop.select),
    stringsAsFactors = FALSE
  )
}

# Extract design parameters manually
extract_design_data <- function(boinet_result) {
  params <- data.frame(
    parameter = c("Target Toxicity Rate (φ)", "Target Efficacy Rate (δ)", 
                  "Lower Toxicity Boundary (λ₁)", "Upper Toxicity Boundary (λ₂)",
                  "Efficacy Boundary (η₁)", "Early Stop Rate (%)", 
                  "Average Duration (days)", "Number of Simulations"),
    value = c(boinet_result$phi, boinet_result$delta, 
              boinet_result$lambda1, boinet_result$lambda2,
              boinet_result$eta1, boinet_result$prop.stop, 
              boinet_result$duration, boinet_result$n.sim),
    stringsAsFactors = FALSE
  )
  
  # Add time-specific parameters if available
  if (!is.null(boinet_result$tau.T)) {
    time_params <- data.frame(
      parameter = c("Toxicity Assessment Window (days)", 
                    "Efficacy Assessment Window (days)",
                    "Accrual Rate (days)"),
      value = c(boinet_result$tau.T, boinet_result$tau.E, boinet_result$accrual),
      stringsAsFactors = FALSE
    )
    params <- rbind(params, time_params)
  }
  
  return(params)
}

# Extract data
oc_data <- extract_oc_data(result)
design_data <- extract_design_data(result)

# View operating characteristics
oc_data

## ----design_params------------------------------------------------------------
# View design parameters
design_data

## ----design_types, eval=FALSE-------------------------------------------------
# # The extraction functions work with any boinet result type:
# # - tite.boinet results
# # - tite.gboinet results
# # - boinet results
# # - gboinet results
# 
# # Example usage:
# # oc_data <- extract_oc_data(any_boinet_result)
# # design_data <- extract_design_data(any_boinet_result)

## ----dose_analysis------------------------------------------------------------
# Find optimal dose
optimal_dose <- oc_data$dose_level[which.max(oc_data$selection_prob)]
cat("Optimal dose level:", optimal_dose, "\n")
cat("Selection probability:", round(max(oc_data$selection_prob), 1), "%\n")

# Doses with reasonable selection probability (>10%)
viable_doses <- oc_data[oc_data$selection_prob > 10, ]
viable_doses

## ----safety_analysis----------------------------------------------------------
# Assess safety profile
safety_summary <- oc_data %>%
  mutate(
    safety_category = case_when(
      toxicity_prob <= 0.10 ~ "Low toxicity",
      toxicity_prob <= 0.25 ~ "Moderate toxicity", 
      TRUE ~ "High toxicity"
    )
  ) %>%
  group_by(safety_category) %>%
  summarise(
    n_doses = n(),
    total_selection_prob = sum(selection_prob),
    avg_patients = mean(n_patients),
    .groups = "drop"
  )

safety_summary

## ----tradeoff_analysis--------------------------------------------------------
# Analyze efficacy-toxicity trade-off
tradeoff_data <- oc_data %>%
  mutate(
    benefit_risk_ratio = efficacy_prob / (toxicity_prob + 0.01),  # Add small constant to avoid division by zero
    utility_score = efficacy_prob - 2 * toxicity_prob  # Simple utility function
  ) %>%
  arrange(desc(utility_score))

# Top doses by utility
head(tradeoff_data[, c("dose_level", "toxicity_prob", "efficacy_prob", 
                       "selection_prob", "utility_score")], 3)

## ----visualization, eval=ggplot2_available, fig.cap="Dose Selection Probabilities"----
if (ggplot2_available) {
  oc_data %>%
    ggplot(aes(x = dose_level, y = selection_prob)) +
    geom_col(fill = "steelblue", alpha = 0.7) +
    geom_text(aes(label = paste0(round(selection_prob, 1), "%")), 
              vjust = -0.3, size = 3.5) +
    labs(
      x = "Dose Level",
      y = "Selection Probability (%)",
      title = "TITE-BOIN-ET: Dose Selection Performance",
      subtitle = paste("Optimal dose:", optimal_dose, 
                      "selected in", round(max(oc_data$selection_prob), 1), "% of trials")
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
      plot.subtitle = element_text(hjust = 0.5, size = 12)
    )
} else {
  cat("ggplot2 package not available. Install with: install.packages('ggplot2')\n")
}

## ----efficacy_toxicity_plot, eval=ggplot2_available, fig.cap="Efficacy vs Toxicity Trade-off"----
if (ggplot2_available) {
  oc_data %>%
    ggplot(aes(x = toxicity_prob, y = efficacy_prob)) +
    geom_point(aes(size = selection_prob), alpha = 0.7, color = "darkred") +
    geom_text(aes(label = dose_level), vjust = -1.2) +
    scale_size_continuous(name = "Selection\nProbability (%)", range = c(2, 10)) +
    labs(
      x = "True Toxicity Probability",
      y = "True Efficacy Probability", 
      title = "Efficacy-Toxicity Profile",
      subtitle = "Point size represents selection probability"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
      plot.subtitle = element_text(hjust = 0.5, size = 12)
    )
} else {
  cat("ggplot2 package not available for visualization.\n")
}

## ----oc_table-----------------------------------------------------------------
# Create a nicely formatted table using base R
create_oc_summary <- function(oc_data) {
  formatted_data <- oc_data
  formatted_data$toxicity_prob <- round(formatted_data$toxicity_prob, 3)
  formatted_data$efficacy_prob <- round(formatted_data$efficacy_prob, 3)
  formatted_data$n_patients <- round(formatted_data$n_patients, 1)
  formatted_data$selection_prob <- round(formatted_data$selection_prob, 1)
  
  # Rename columns for display
  names(formatted_data) <- c("Dose Level", "True Toxicity Prob", 
                           "True Efficacy Prob", "Avg N Treated", 
                           "Selection Prob (%)")
  
  return(formatted_data)
}

# Create formatted table
formatted_oc <- create_oc_summary(oc_data)
print(formatted_oc)

## ----design_table-------------------------------------------------------------
# Create formatted design parameters table
create_design_summary <- function(design_data) {
  formatted_design <- design_data
  formatted_design$value <- round(as.numeric(formatted_design$value), 3)
  
  # Clean up parameter names
  names(formatted_design) <- c("Parameter", "Value")
  
  return(formatted_design)
}

formatted_design <- create_design_summary(design_data)
print(formatted_design)

## ----summary_output-----------------------------------------------------------
# Enhanced summary automatically detects design type
summary(result)

## ----export_data, eval=FALSE--------------------------------------------------
# # Export data for external analysis
# write.csv(oc_data, "operating_characteristics.csv", row.names = FALSE)
# write.csv(design_data, "design_parameters.csv", row.names = FALSE)
# 
# # Save as RDS for R users
# saveRDS(list(oc_data = oc_data, design_data = design_data), "boinet_results.rds")
# 
# # Create summary report
# summary_stats <- list(
#   optimal_dose = optimal_dose,
#   max_selection_prob = max(oc_data$selection_prob),
#   early_stop_rate = result$prop.stop,
#   avg_duration = result$duration,
#   design_type = class(result)[1]
# )
# 
# saveRDS(summary_stats, "summary_statistics.rds")

## ----validation---------------------------------------------------------------
# Always check your results make sense
total_selection <- sum(oc_data$selection_prob) + as.numeric(result$prop.stop)
cat("Total probability (selection + early stop):", round(total_selection, 1), "%\n")

# Check for reasonable dose allocation
cat("Patient allocation summary:\n")
print(summary(oc_data$n_patients))

# Verify dose ordering makes sense
if (all(diff(oc_data$toxicity_prob) >= 0)) {
  cat("✓ Toxicity probabilities are non-decreasing\n")
} else {
  cat("⚠ Warning: Toxicity probabilities not monotonic\n")
}

## ----reproducibility----------------------------------------------------------
# Document analysis parameters
analysis_info <- list(
  date = Sys.Date(),
  design_type = class(result)[1],
  r_version = R.version.string,
  boinet_version = as.character(packageVersion("boinet")),
  key_findings = list(
    optimal_dose = optimal_dose,
    selection_probability = max(oc_data$selection_prob),
    early_stop_rate = as.numeric(result$prop.stop)
  )
)

# Display analysis info
str(analysis_info)

## ----utility_functions--------------------------------------------------------
# Create reusable utility functions
calculate_utility_score <- function(eff_prob, tox_prob, eff_weight = 1, tox_weight = 2) {
  eff_weight * eff_prob - tox_weight * tox_prob
}

find_best_doses <- function(oc_data, n_top = 3) {
  oc_data %>%
    arrange(desc(selection_prob)) %>%
    head(n_top) %>%
    select(dose_level, selection_prob, toxicity_prob, efficacy_prob)
}

# Use utility functions
oc_data$utility <- calculate_utility_score(oc_data$efficacy_prob, oc_data$toxicity_prob)
top_doses <- find_best_doses(oc_data)

cat("Top doses by selection probability:\n")
print(top_doses)

## ----sensitivity_analysis-----------------------------------------------------
# Analyze sensitivity to design parameters
sensitivity_summary <- data.frame(
  metric = c("Optimal Dose", "Max Selection %", "Early Stop %", 
             "Avg Duration", "Total Patients"),
  value = c(optimal_dose, round(max(oc_data$selection_prob), 1),
            round(result$prop.stop, 1), round(result$duration, 0),
            round(sum(oc_data$n_patients), 0)),
  stringsAsFactors = FALSE
)

print(sensitivity_summary)

## ----comparison_framework-----------------------------------------------------
# Framework for comparing multiple designs
create_design_comparison <- function(result_list, design_names) {
  comparison_data <- data.frame()
  
  for (i in seq_along(result_list)) {
    oc_data <- extract_oc_data(result_list[[i]])
    optimal_dose <- oc_data$dose_level[which.max(oc_data$selection_prob)]
    
    summary_row <- data.frame(
      design = design_names[i],
      optimal_dose = optimal_dose,
      max_selection = max(oc_data$selection_prob),
      early_stop = result_list[[i]]$prop.stop,
      avg_duration = result_list[[i]]$duration,
      stringsAsFactors = FALSE
    )
    
    comparison_data <- rbind(comparison_data, summary_row)
  }
  
  return(comparison_data)
}

# Example usage (would work with multiple results)
cat("Comparison framework ready for multiple design evaluation\n")

Try the boinet package in your browser

Any scripts or data that you put into this service are public.

boinet documentation built on June 27, 2025, 1:08 a.m.