## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5,
  warning = FALSE,
  message = FALSE
)

## ----quickstart, eval=FALSE---------------------------------------------------
# library(PsyML)
# 
# # Basic usage with simulated data
# result <- ml_sample_size(
#   task = "classification",
#   metric = "auc",
#   target = 0.80,
#   seed = 2026,
#   reps = 100
# )
# 
# # View recommendation
# result$recommend_n
# # [1] 600

## ----example1, eval=FALSE-----------------------------------------------------
# library(PsyML)
# 
# # Simulate a classification problem
# result <- ml_sample_size(
#   task = "classification",
#   metric = "auc",
#   target = 0.80,
#   n_grid = c(100, 200, 300, 400, 600, 800, 1000),
#   reps = 100,  # 100 Monte Carlo repetitions
#   sim_params = list(
#     p = 20,           # 20 predictors
#     prevalence = 0.20, # 20% positive class
#     signal = 2.5       # Moderate signal (AUC ~0.85-0.90 achievable)
#   ),
#   seed = 123
# )

## ----interpret, eval=FALSE----------------------------------------------------
# # View full results
# print(result)
# 
# # Recommended sample size
# result$recommend_n
# # [1] 600
# 
# # Summary table with SE of success proportion
# result$summary[, c("n", "mean", "sd", "p_meet", "se_p_meet")]
# #     n  mean    sd p_meet se_p_meet
# # 1 100 0.760 0.025   0.12     0.032
# # 2 200 0.795 0.018   0.45     0.050
# # 3 300 0.815 0.015   0.78     0.041
# # 4 400 0.825 0.012   0.92     0.027
# # 5 600 0.840 0.010   0.98     0.014
# # ...

## ----plot1, eval=FALSE--------------------------------------------------------
# # Plot the learning curve
# plot_learning_curve(result)

## ----reps_guidance, eval=FALSE------------------------------------------------
# # For exploratory analysis
# result_quick <- ml_sample_size(
#   task = "classification",
#   target = 0.80,
#   seed = 2026,
#   reps = 50  # Quick exploration
# )
# 
# # For publication-quality results
# result_precise <- ml_sample_size(
#   task = "classification",
#   target = 0.80,
#   seed = 2026,
#   reps = 200  # High precision
# )

## ----small_data, eval=FALSE---------------------------------------------------
# # Load a small dataset
# data(PimaIndiansDiabetes, package = "mlbench")
# 
# # Use 5 independent test partitions
# result <- ml_sample_size(
#   data = PimaIndiansDiabetes,
#   formula = diabetes ~ .,
#   task = "classification",
#   metric = "auc",
#   target = 0.75,
#   positive = "pos",
#   seed = 2026,
#   reps = 100,
#   n_outer_splits = 5,  # 5 independent partitions
#   verbose = TRUE
# )

## ----multi_partition, eval=FALSE----------------------------------------------
# # View results across partitions
# result$outer_splits_results
# # $median: 50       # Median n* (use this as recommendation)
# # $range: [50, 150] # Range of estimates
# # $cv: 0.559        # Coefficient of variation
# 
# # If CV > 50%, there's high uncertainty
# # Report: "n* = 50 (range: 50-150, CV = 56%)"

## ----bootstrap, eval=FALSE----------------------------------------------------
# result <- ml_sample_size(
#   task = "classification",
#   target = 0.80,
#   seed = 2026,
#   reps = 100,
#   bootstrap_ci = TRUE,  # Enable bootstrap
#   n_boot = 1000         # 1000 resamples
# )
# 
# # View 95% CI (values will vary)
# result$recommend_n_ci
# # $ci_lower: 400   # Lower bound of 95% CI
# # $ci_upper: 800   # Upper bound of 95% CI
# # $ci_median: 600  # Bootstrap median

## ----multi_model, eval=FALSE--------------------------------------------------
# result <- ml_sample_size(
#   task = "classification",
#   model = c("rf", "xgboost", "glm"),  # Compare 3 models
#   metric = "auc",
#   target = 0.80,
#   seed = 2026,
#   reps = 50
# )
# 
# # View recommendations by model (values will vary)
# result$recommend_n
# # $rf:      600   # or higher depending on data
# # $xgboost: 600   # similar to RF
# # $glm:     200   # typically needs less data
# 
# # GLM needs less data but may have lower asymptotic performance
# # RF/XGBoost need more data but achieve higher maximum AUC

## ----diagnostics, eval=FALSE--------------------------------------------------
# # Check fit diagnostics
# result$curve_diagnostics
# # $pseudo_r2: 0.967    # Good: > 0.95
# # $rmse_fit: 0.008     # Low fitting error
# # $fit_quality: "good" # Automatic classification
# 
# # Fit quality interpretation:
# # - "good":       R² ≥ 0.95 (safe to extrapolate)
# # - "acceptable": R² ≥ 0.80 (extrapolate with caution)
# # - "poor":       R² < 0.80 (do not extrapolate)

## ----estimate_n, eval=FALSE---------------------------------------------------
# # What n is needed for AUC = 0.85?
# estimate_n(result, target_metric = 0.85)
# # [1] 1250
# 
# # Warnings are issued if:
# # - Target exceeds asymptote
# # - n exceeds 2x max observed
# # - Fit quality is poor

## ----plateau, eval=FALSE------------------------------------------------------
# # Where does performance plateau?
# 
# # Absolute delta (within 0.01 of asymptote)
# estimate_n_plateau(result, delta = 0.01)
# # [1] 8500
# 
# # Relative delta (within 1% of target)
# estimate_n_plateau(result, delta = 0.01, relative = TRUE)
# # Using relative delta: 0.01 x 0.8 = 0.008
# # [1] 12000

## ----regression, eval=FALSE---------------------------------------------------
# result <- ml_sample_size(
#   task = "regression",
#   metric = "rmse",        # Or "mae", "r2"
#   target = 1.0,           # Target RMSE ≤ 1.0
#   target_dir = "lower_better",  # Auto-detected for RMSE
#   seed = 2026,
#   reps = 100,
#   sim_params = list(
#     p = 15,
#     noise_sd = 1.5  # Controls signal-to-noise ratio
#   )
# )

## ----best1, eval=FALSE--------------------------------------------------------
# # Quick exploration with low R
# result_explore <- ml_sample_size(
#   task = "classification",
#   target = 0.80,
#   seed = 2026,
#   reps = 30,
#   n_grid = seq(100, 1000, by = 100)
# )
# 
# # Refine with higher R after identifying the region
# result_final <- ml_sample_size(
#   task = "classification",
#   target = 0.80,
#   seed = 2026,
#   reps = 200,
#   n_grid = c(300, 400, 500, 600, 700, 800)  # Focus on relevant range
# )

## ----best2, eval=FALSE--------------------------------------------------------
# # Before extrapolating:
# if (result$curve_diagnostics$fit_quality == "poor") {
#   warning("Do not extrapolate - use only observed values")
# }

## ----best4, eval=FALSE--------------------------------------------------------
# # Add a safety margin (e.g., 20-30%)
# n_star <- result$recommend_n
# n_with_tuning <- ceiling(n_star * 1.25)

## ----trouble1, eval=FALSE-----------------------------------------------------
# # If curve_fit is NULL or fit_quality is "poor":
# # 1. Increase reps
# result <- ml_sample_size(..., reps = 200)
# 
# # 2. Expand n_grid range
# result <- ml_sample_size(..., n_grid = c(50, 100, 200, 500, 1000, 2000, 5000))
# 
# # 3. Use only interpolation (don't extrapolate)

## ----trouble2, eval=FALSE-----------------------------------------------------
# # If CV > 50% with multiple partitions:
# # 1. This is expected for small datasets - report the range
# # 2. Consider using the upper bound for safety
# # 3. Acknowledge uncertainty in your report

## ----trouble3, eval=FALSE-----------------------------------------------------
# # If recommend_n is NA or Inf:
# # 1. Check if target exceeds the asymptote
# result$curve_fit  # Look at coefficient 'a'
# 
# # 2. Lower your target or increase signal strength
# result <- ml_sample_size(..., target = 0.75)  # Lower target
# 
# # 3. Use a different algorithm
# result <- ml_sample_size(..., model = "glm")  # Simpler model

## ----sessioninfo, eval=FALSE--------------------------------------------------
# sessionInfo()

