## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE, comment = "#>",
  fig.width = 7, fig.height = 3.6, dpi = 96, fig.align = "center"
)

## ----library------------------------------------------------------------------
library(imbalanceKit)

## ----data---------------------------------------------------------------------
x <- banana[, c("At1", "At2")]
y <- banana$Class
table(y)

## ----plot-helper--------------------------------------------------------------
col_neg <- "#9aa5b1"
col_pos <- "#c0392b"
col_syn <- "#1f6fb2"

plot_classes <- function(x, y, x_syn = NULL, main = "") {
  x <- as.matrix(x)
  plot(x, type = "n", xlab = "At1", ylab = "At2", main = main, asp = 1)
  if (!is.null(x_syn)) {
    points(as.matrix(x_syn), col = adjustcolor(col_syn, 0.45), pch = 17, cex = 0.5)
  }
  neg <- y != "positive"
  points(x[neg, , drop = FALSE], col = col_neg, pch = 1, cex = 0.5)
  points(x[!neg, , drop = FALSE], col = col_pos, pch = 16, cex = 0.6)
}

par(mar = c(4, 4, 2, 1))
plot_classes(x, y, main = "banana")

## ----complexity---------------------------------------------------------------
complexity(x, y, measures = c("IR", "R", "R_aug", "N1", "N3", "N4"), seed = 1)

## ----smote--------------------------------------------------------------------
set.seed(1)
m <- SMOTE(x, y)
names(m)
table(m$y_new)

## ----compare, fig.height = 6.5------------------------------------------------
set.seed(1)
res <- list(
  SMOTE    = SMOTE(x, y),
  BLSMOTE  = BLSMOTE(x, y),
  BiSMOTE  = BiSMOTE(x, y),
  SMOTEWB  = SMOTEWB(x, y)
)

par(mfrow = c(2, 2), mar = c(4, 4, 2, 1))
for (nm in names(res)) {
  plot_classes(x, y, res[[nm]]$x_syn, main = nm)
}

## ----datrel-------------------------------------------------------------------
set.seed(1)
m <- SMOTE(x, y)
d <- DatRel(x, y, x_syn = m$x_syn, y_syn = m$y_syn)
d$n_relocated

## ----datrel-plot--------------------------------------------------------------
moved <- rowSums(abs(m$x_syn - d$x_syn)) > 0

par(mfrow = c(1, 2), mar = c(4, 4, 2, 1))
plot_classes(x, y, m$x_syn[!moved, ], main = "SMOTE")
points(m$x_syn[moved, ], col = "#e67e22", pch = 17, cex = 0.6)
plot_classes(x, y, d$x_syn[!moved, ], main = "SMOTE + DatRel")
points(d$x_syn[moved, ], col = "#e67e22", pch = 17, cex = 0.6)

## ----evaluate-----------------------------------------------------------------
split_data <- function(y, p_train = 0.7) {
  idx <- unlist(lapply(split(seq_along(y), y), function(i) {
    i[sample.int(length(i), round(p_train * length(i)))]
  }))
  sort(idx)
}

fit_eval <- function(x_train, y_train, x_test, y_test) {
  fit <- rpart::rpart(y ~ ., data = data.frame(x_train, y = y_train))
  pred <- predict(fit, data.frame(x_test), type = "class")
  evaluate(y_test, y_pred = pred, positive = "positive",
           metrics = c("BACC", "GMEAN", "F1", "MCC"))
}

set.seed(2026)
results <- lapply(1:10, function(r) {
  i_train <- split_data(y)
  x_tr <- x[i_train, ]; y_tr <- y[i_train]
  x_te <- x[-i_train, ]; y_te <- y[-i_train]

  s <- SMOTE(x_tr, y_tr)
  d <- DatRel(x_tr, y_tr, s$x_syn, s$y_syn)

  rbind(
    original         = fit_eval(x_tr, y_tr, x_te, y_te),
    SMOTE            = fit_eval(s$x_new, s$y_new, x_te, y_te),
    `SMOTE + DatRel` = fit_eval(d$x_new, d$y_new, x_te, y_te)
  )
})

round(Reduce(`+`, results) / length(results), 3)

