# Result Formatting with Enhanced boinet Package

    library(boinet)
    library(dplyr)

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

# Overview

The boinet package provides flexible result formatting capabilities for all BOIN-ET design family results. This vignette demonstrates how to format simulation results for analysis and reporting using the built-in functionality and standard R tools.

## Key Approach

While the package continues to evolve with enhanced formatting functions, this vignette shows how to work with existing boinet results using standard R data manipulation techniques.

## Basic Workflow

### Step 1: Run Simulation

First, run your BOIN-ET simulation as usual:

    # 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
    )

### Step 2: Extract and Format Data

#### Manual Data 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
    #>   dose_level toxicity_prob efficacy_prob n_patients selection_prob
    #> 1          1          0.02          0.10        8.2            5.2
    #> 2          2          0.08          0.20       12.5           18.7
    #> 3          3          0.15          0.35       15.8           42.1
    #> 4          4          0.25          0.50       10.3           28.3
    #> 5          5          0.40          0.65        7.2            5.7

    # View design parameters
    design_data
    #>                            parameter   value
    #> 1           Target Toxicity Rate (φ)    0.30
    #> 2           Target Efficacy Rate (δ)    0.60
    #> 3       Lower Toxicity Boundary (λ₁)    0.03
    #> 4       Upper Toxicity Boundary (λ₂)    0.42
    #> 5             Efficacy Boundary (η₁)    0.36
    #> 6                Early Stop Rate (%)    3.20
    #> 7            Average Duration (days)  156.30
    #> 8              Number of Simulations 1000.00
    #> 9  Toxicity Assessment Window (days)   28.00
    #> 10 Efficacy Assessment Window (days)   42.00
    #> 11               Accrual Rate (days)    7.00

## Working with Different Design Types

The same extraction approach works with all BOIN-ET design family members:

    # 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)

## Custom Analysis Examples

### Dose Selection Analysis

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

    # Doses with reasonable selection probability (>10%)
    viable_doses <- oc_data[oc_data$selection_prob > 10, ]
    viable_doses
    #>   dose_level toxicity_prob efficacy_prob n_patients selection_prob
    #> 2          2          0.08          0.20       12.5           18.7
    #> 3          3          0.15          0.35       15.8           42.1
    #> 4          4          0.25          0.50       10.3           28.3

### 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
    #> # A tibble: 3 × 4
    #>   safety_category   n_doses total_selection_prob avg_patients
    #>   <chr>               <int>                <dbl>        <dbl>
    #> 1 High toxicity           1                  5.7          7.2
    #> 2 Low toxicity            2                 23.9         10.4
    #> 3 Moderate toxicity       2                 70.4         13.0

### Efficacy-Toxicity Trade-off

    # 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)
    #>   dose_level toxicity_prob efficacy_prob selection_prob utility_score
    #> 1          1          0.02          0.10            5.2          0.06
    #> 2          3          0.15          0.35           42.1          0.05
    #> 3          2          0.08          0.20           18.7          0.04

## Creating Visualizations

    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")
    }

Dose Selection Probabilities

    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")
    }

Efficacy vs Toxicity Trade-off

## Creating Summary Tables

### Operating Characteristics 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)
    #>   Dose Level True Toxicity Prob True Efficacy Prob Avg N Treated
    #> 1          1               0.02               0.10           8.2
    #> 2          2               0.08               0.20          12.5
    #> 3          3               0.15               0.35          15.8
    #> 4          4               0.25               0.50          10.3
    #> 5          5               0.40               0.65           7.2
    #>   Selection Prob (%)
    #> 1                5.2
    #> 2               18.7
    #> 3               42.1
    #> 4               28.3
    #> 5                5.7

### Design Parameters 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)
    #>                            Parameter   Value
    #> 1           Target Toxicity Rate (φ)    0.30
    #> 2           Target Efficacy Rate (δ)    0.60
    #> 3       Lower Toxicity Boundary (λ₁)    0.03
    #> 4       Upper Toxicity Boundary (λ₂)    0.42
    #> 5             Efficacy Boundary (η₁)    0.36
    #> 6                Early Stop Rate (%)    3.20
    #> 7            Average Duration (days)  156.30
    #> 8              Number of Simulations 1000.00
    #> 9  Toxicity Assessment Window (days)   28.00
    #> 10 Efficacy Assessment Window (days)   42.00
    #> 11               Accrual Rate (days)    7.00

## Enhanced Summary Output

The package provides enhanced summary methods for all boinet result types:

    # Enhanced summary automatically detects design type
    summary(result)
    #> TITE-BOIN-ET Design Operating Characteristics
    #> =========================================
    #>
    #> Design Parameters:
    #>   Target Toxicity Probability: 0.30
    #>   Target Efficacy Probability: 0.60
    #>   Trial Duration: 156.3 days
    #>   Early Stop Probability: 3.2%
    #>
    #> Operating Characteristics by Dose Level:
    #> # A tibble: 5 × 6
    #>   dose_level toxicity_prob efficacy_prob n_patients selection_prob selection_pct
    #>   <chr>              <dbl>         <dbl>      <dbl>          <dbl> <chr>
    #> 1 1                   0.02          0.1         8.2          0.052 5.2%
    #> 2 2                   0.08          0.2        12.5          0.187 18.7%
    #> 3 3                   0.15          0.35       15.8          0.421 42.1%
    #> 4 4                   0.25          0.5        10.3          0.283 28.3%
    #> 5 5                   0.4           0.65        7.2          0.057 5.7%

## Exporting Data

    # 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")

## Best Practices

### 1. Consistent Workflow

Always follow the pattern: simulate first, then extract and analyze data.

### 2. Data 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")
    #> Total probability (selection + early stop): 103.2 %

    # Check for reasonable dose allocation
    cat("Patient allocation summary:\n")
    #> Patient allocation summary:
    print(summary(oc_data$n_patients))
    #>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
    #>     7.2     8.2    10.3    10.8    12.5    15.8

    # 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")
    }
    #> ✓ Toxicity probabilities are non-decreasing

### 3. Reproducible Analysis

    # 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)
    #> List of 5
    #>  $ date          : Date[1:1], format: "2025-10-25"
    #>  $ design_type   : chr "tite.boinet"
    #>  $ r_version     : chr "R version 4.5.1 (2025-06-13 ucrt)"
    #>  $ boinet_version: chr "1.5.0"
    #>  $ key_findings  :List of 3
    #>   ..$ optimal_dose         : chr "3"
    #>   ..$ selection_probability: num 42.1
    #>   ..$ early_stop_rate      : num 3.2

### 4. Custom 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")
    #> Top doses by selection probability:
    print(top_doses)
    #>   dose_level selection_prob toxicity_prob efficacy_prob
    #> 1          3           42.1          0.15          0.35
    #> 2          4           28.3          0.25          0.50
    #> 3          2           18.7          0.08          0.20

## Advanced Analysis Examples

### 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)
    #>            metric value
    #> 1    Optimal Dose     3
    #> 2 Max Selection %  42.1
    #> 3    Early Stop %   3.2
    #> 4    Avg Duration   156
    #> 5  Total Patients    54

### Comparative Analysis 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")
    #> Comparison framework ready for multiple design evaluation

## Conclusion

The boinet package provides a solid foundation for analyzing BOIN-ET simulation results. Using standard R data manipulation techniques, you can:

- Extract key information from simulation results
- Create custom analyses tailored to your needs
- Generate publication-quality summaries and visualizations
- Export data for further analysis or reporting
- Build reproducible workflows for consistent analysis

As the package continues to evolve, additional convenience functions will be added, but the core approach of extracting and analyzing the structured results remains consistent across all BOIN-ET design types.

For publication-ready tables, see the `gt-integration` vignette. For complete reporting workflows, see the `quarto-workflow` vignette.