## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

## ----eskin_usage, eval=FALSE--------------------------------------------------
# fit_eskin <- AddiVortes(
#   y = y_train,
#   x = x_train,
#   cat.onehot = FALSE,
#   showProgress = FALSE
# )

## ----simulate_data, message=FALSE, warning=FALSE------------------------------
library(AddiVortes)

set.seed(123)
n <- 400

x <- data.frame(
  age = rnorm(n, mean = 40, sd = 10),
  income = runif(n, 20, 120), # income in thousands
  region = sample(c("East", "North", "South", "West"), n, replace = TRUE),
  product = sample(c("Basic", "Premium", "Deluxe"), n, replace = TRUE),
  stringsAsFactors = FALSE
)

# True response: depends on continuous and categorical variables
region_effect <- ifelse(x$region == "North", 5,
  ifelse(x$region == "South", -5, 0)
)
product_effect <- ifelse(x$product == "Premium", 10,
  ifelse(x$product == "Deluxe", 20, 0)
)

y <- 0.3 * x$age +
  0.1 * x$income +
  region_effect +
  product_effect +
  rnorm(n, sd = 3)

## ----inspect_encoding---------------------------------------------------------
# Show the first few rows of x before encoding
head(x, 5)

## ----show_encoded-------------------------------------------------------------
# Manually inspect the encoding applied by AddiVortes
enc_result <- AddiVortes:::encodeCategories_internal(x, catScaling = 1)
head(enc_result$encoded, 5)

## ----fit_model, results='hide'------------------------------------------------
# Split into training and test sets
set.seed(42)
train_idx <- sample(n, 300)

x_train <- x[train_idx, ]
y_train <- y[train_idx]
x_test <- x[-train_idx, ]
y_test <- y[-train_idx]

fit <- AddiVortes(
  y = y_train,
  x = x_train,
  m = 50,
  totalMCMCIter = 500,
  mcmcBurnIn = 100,
  catScaling = 1, # default: binary columns span [0, 1]
  cat.onehot = TRUE, # default: one-hot encoding
  showProgress = FALSE
)

## ----model_summary------------------------------------------------------------
cat("In-sample RMSE:", round(fit$inSampleRmse, 3), "\n")

# The catEncoding field records how the encoding was built
cat("\nReference levels used:\n")
for (j in fit$catEncoding$catColIndices) {
  orig_col <- fit$catEncoding$origColNames[j]
  ref_lev <- fit$catEncoding$colEncodings[[j]]$levels[1]
  all_lev <- fit$catEncoding$colEncodings[[j]]$levels
  cat(
    " ", orig_col, ": reference =", ref_lev,
    "| all levels:", paste(all_lev, collapse = ", "), "\n"
  )
}

## ----predictions, results='hide'----------------------------------------------
preds <- predict(fit, x_test, showProgress = FALSE)

## ----evaluate-----------------------------------------------------------------
rmse_test <- sqrt(mean((y_test - preds)^2))
cat("Test RMSE:", round(rmse_test, 3), "\n")

## ----plot_predictions, fig.width=7, fig.height=5, fig.align='center'----------
# Colour observations by product category
prod_cols <- c("Basic" = "steelblue", "Premium" = "darkorange", "Deluxe" = "darkgreen")
point_cols <- prod_cols[x_test$product]

plot(y_test, preds,
  col = point_cols, pch = 19, cex = 0.8,
  xlab = "Observed values",
  ylab = "Predicted values",
  main = "Predicted vs. Observed (coloured by product category)"
)
abline(0, 1, lwd = 2, lty = 2, col = "grey40")
legend("topleft",
  legend = names(prod_cols),
  col = prod_cols,
  pch = 19, title = "Product", bty = "n"
)

## ----unseen_level-------------------------------------------------------------
# Create a test point with an unseen product level "Luxury"
x_new <- data.frame(
  age = 45,
  income = 80,
  region = "North",
  product = "Luxury", # unseen level
  stringsAsFactors = FALSE
)

## ----unseen_predict, results='hide'-------------------------------------------
pred_new <- predict(fit, x_new, showProgress = FALSE)

## ----show_unseen--------------------------------------------------------------
cat(
  "Prediction for unseen category 'Luxury' (treated as 'Basic'):",
  round(pred_new, 3), "\n"
)

## ----catscaling_comparison, results='hide'------------------------------------
fit_cs2 <- AddiVortes(
  y = y_train,
  x = x_train,
  m = 50,
  totalMCMCIter = 500,
  mcmcBurnIn = 100,
  catScaling = 2, # give categorical differences twice as much weight
  cat.onehot = TRUE,
  showProgress = FALSE
)

## ----catscaling_results, results='hide'---------------------------------------
preds_cs2 <- predict(fit_cs2, x_test, showProgress = FALSE)

## ----catscaling_rmse----------------------------------------------------------
cat("Test RMSE (catScaling = 1):", round(rmse_test, 3), "\n")
cat("Test RMSE (catScaling = 2):", round(sqrt(mean((y_test - preds_cs2)^2)), 3), "\n")

## ----fit_eskin, results='hide'------------------------------------------------
# Use factors with fixed levels so integer codes stay aligned at prediction
x_train_f <- x_train
x_test_f <- x_test
x_train_f$region <- factor(x_train$region, levels = c("East", "North", "South", "West"))
x_train_f$product <- factor(x_train$product, levels = c("Basic", "Deluxe", "Premium"))
x_test_f$region <- factor(x_test$region, levels = levels(x_train_f$region))
x_test_f$product <- factor(x_test$product, levels = levels(x_train_f$product))

fit_eskin <- AddiVortes(
  y = y_train,
  x = x_train_f,
  m = 50,
  totalMCMCIter = 500,
  mcmcBurnIn = 100,
  cat.onehot = FALSE, # Eskin distance on integer-coded categories
  showProgress = FALSE
)

## ----eskin_predictions, results='hide'----------------------------------------
preds_eskin <- predict(fit_eskin, x_test_f, showProgress = FALSE)

## ----eskin_comparison---------------------------------------------------------
rmse_eskin <- sqrt(mean((y_test - preds_eskin)^2))
cat("Test RMSE (one-hot, catScaling = 1):", round(rmse_test, 3), "\n")
cat("Test RMSE (Eskin):                   ", round(rmse_eskin, 3), "\n")
cat("In-sample RMSE (one-hot):", round(fit$inSampleRmse, 3), "\n")
cat("In-sample RMSE (Eskin):  ", round(fit_eskin$inSampleRmse, 3), "\n")

## ----plot_eskin_comparison, fig.width=7, fig.height=5, fig.align='center'-----
plot(y_test, preds,
  col = adjustcolor("steelblue", alpha.f = 0.7), pch = 19, cex = 0.8,
  xlab = "Observed values",
  ylab = "Predicted values",
  main = "One-hot vs Eskin: predicted vs observed"
)
points(y_test, preds_eskin,
  col = adjustcolor("darkorange", alpha.f = 0.7), pch = 17, cex = 0.8
)
abline(0, 1, lwd = 2, lty = 2, col = "grey40")
legend("topleft",
  legend = c("One-hot", "Eskin"),
  col = c("steelblue", "darkorange"),
  pch = c(19, 17), bty = "n"
)

