Skip to content

Commit 0a46938

Browse files
authored
Merge pull request #30 from topepo/xgb-3-migration
Changes for new version of xgboost
2 parents 32fd812 + 22868bd commit 0a46938

7 files changed

Lines changed: 70 additions & 31 deletions

File tree

.github/workflows/R-CMD-check.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,12 @@ jobs:
2626
- {os: macos-latest, r: 'release'}
2727

2828
- {os: windows-latest, r: 'release'}
29-
# use 4.0 or 4.1 to check with rtools40's older compiler
30-
- {os: windows-latest, r: 'oldrel-4'}
29+
- {os: windows-latest, r: 'oldrel-1'}
3130

3231
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
3332
- {os: ubuntu-latest, r: 'release'}
3433
- {os: ubuntu-latest, r: 'oldrel-1'}
3534
- {os: ubuntu-latest, r: 'oldrel-2'}
36-
- {os: ubuntu-latest, r: 'oldrel-3'}
37-
- {os: ubuntu-latest, r: 'oldrel-4'}
3835

3936
env:
4037
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ License: MIT + file LICENSE
1717
URL: https://github.com/holub008/xrf
1818
BugReports: https://github.com/holub008/xrf/issues
1919
Depends:
20-
R (>= 4.1.0)
20+
R (>= 4.3.0)
2121
Imports:
2222
cli,
2323
dplyr,
@@ -26,7 +26,7 @@ Imports:
2626
Matrix,
2727
methods,
2828
rlang,
29-
xgboost (>= 0.71.2)
29+
xgboost (>= 3.1.2.1)
3030
Suggests:
3131
covr,
3232
testthat (>= 3.0.0)

R/xrf.R

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ condition_xgb_control <- function(
4949
data_mutated[[response_var]] <- integer_response - min(integer_response)
5050
}
5151

52+
xgb_control$objective <- get_xgboost_objective(family, call = call)
5253
list(xgb_control = xgb_control, data = data_mutated)
5354
}
5455

@@ -70,22 +71,6 @@ xrf_preconditions <- function(
7071
)
7172
}
7273

73-
if (!('nrounds' %in% names(xgb_control))) {
74-
cli::cli_abort(
75-
"Must supply an {.arg nrounds} list element to the {.arg xgb_control}
76-
argument.",
77-
call = call
78-
)
79-
}
80-
81-
if ('objective' %in% names(xgb_control)) {
82-
cli::cli_abort(
83-
"User may not supply an {.arg objective} element to the {.arg xgb_control}
84-
argument.",
85-
call = call
86-
)
87-
}
88-
8974
if (!(response_var %in% colnames(data))) {
9075
cli::cli_abort(
9176
"Response variable {.var {response_var}} not present in supplied data",
@@ -507,6 +492,14 @@ xrf <- function(object, ...) {
507492
#' @importFrom stats terms
508493
#' @importFrom stats update
509494
#'
495+
#' @details
496+
#'
497+
#' In November 2025, the new version of \pkg{xgboost} (3.1.2.1) introduced
498+
#' significant breaking changes. This version of \pkg{xrf} can reproduce
499+
#' predictions from older versions of \pkg{xgboost}. However, there are likely
500+
#' to be differences in \pkg{xrf} model fits between old and new versions of
501+
#' \pkg{xgboost}.
502+
#'
510503
#' @references
511504
#' Friedman, J. H., & Popescu, B. E. (2008). Predictive learning via rule
512505
#' ensembles. \emph{The Annals of Applied Statistics, 2}(3), 916-954.
@@ -557,12 +550,10 @@ xrf.formula <- function(
557550
xgb_control <- within(xgb_control, rm(nrounds))
558551

559552
if (is.null(prefit_xgb)) {
560-
m_xgb <- xgboost(
561-
data = design_matrix,
562-
label = data[[response_var]],
553+
m_xgb <- xgboost::xgb.train(
554+
xgboost::xgb.DMatrix(design_matrix, label = data[[response_var]]),
563555
nrounds = nrounds,
564-
objective = get_xgboost_objective(family),
565-
params = xgb_control,
556+
params = xgb_params(xgb_control),
566557
verbose = 0
567558
)
568559
rules <- extract_xgb_rules(m_xgb)
@@ -793,10 +784,13 @@ summary.xrf <- function(object, ...) {
793784
))
794785
cat(paste0('\n\nOriginal Formula:\n\n'))
795786
cat(smaller_formula(object$base_formula))
796-
cat('\n\nTree model:\n\n')
797-
show(summary(object$xgb))
798-
cat('\n\nGLM:\n\n')
799-
show(summary(object$glm))
787+
cli::cli_rule("Tree model")
788+
cat("\n")
789+
print(object$xgb)
790+
cat("\n")
791+
cli::cli_rule("GLM")
792+
print(object$glm$model)
793+
invisible(object)
800794
}
801795

802796
#' Print an eXtreme RuleFit model
@@ -828,3 +822,20 @@ smaller_formula <- function(x, ...) {
828822
}
829823
chr_form
830824
}
825+
826+
xgb_params <- function(x, call = rlang::caller_env()) {
827+
cl <- rlang::call2("xgb.params", .ns = "xgboost", !!!x)
828+
res <- try(rlang::eval_tidy(cl, data = x), silent = TRUE)
829+
if (inherits(res, "try-error")) {
830+
msg <- as.character(res)
831+
msg <- strsplit(msg, split = ":")[[1]][-(1:3)]
832+
msg <- gsub("\\n", "", msg)
833+
msg <- trimws(msg)
834+
msg <- paste0(msg, collapse = "")
835+
cli::cli_abort(
836+
"There was an error when parsing the xgboost arguments: {msg}",
837+
call = call
838+
)
839+
}
840+
res
841+
}

inst/xgb_1_7_11.R

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# pak::pak(c("xrf", "xgboost"), ask = FALSE)
2+
library(xrf)
3+
library(xgboost)
4+
# xgboost_1.7.11.1 xrf_0.2.2
5+
6+
set.seed(832)
7+
xgb_1_7_11_fit <- xrf(mpg ~ ., data = mtcars[1:28, ], family = "gaussian")
8+
xgb_1_7_11_pred <- predict(xgb_1_7_11_fit, mtcars[29:32, ])
9+
save(xgb_1_7_11_fit, xgb_1_7_11_pred, file = "inst/xgb_1_7_11.RData")
10+
11+
if (!interactive()) {
12+
q("no")
13+
}

inst/xgb_1_7_11.RData

53.9 KB
Binary file not shown.

man/xrf.formula.Rd

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test_xgb_1_7_11.R

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# In November 2025, the new version of xgboost has api changes
2+
# that are breaking changes. See https://github.com/dmlc/xgboost/issues/11430
3+
# This file uses the current CRAN versions to ensure that prediction
4+
# works in updated versions of xrf and xgboost.
5+
6+
test_that('prediction works on xgboost versions < 3.0', {
7+
load(system.file("xgb_1_7_11.RData", package = "xrf"), verbose = FALSE)
8+
xgb_3_1_2_1_pred <- predict(xgb_1_7_11_fit, mtcars[29:32, ])
9+
10+
expect_equal(xgb_1_7_11_pred, xgb_3_1_2_1_pred)
11+
})

0 commit comments

Comments
 (0)