Skip to content

Commit

Permalink
Merge pull request #96 from ModelOriented/cran_submission
Browse files Browse the repository at this point in the history
Cran submission
  • Loading branch information
mayer79 authored Jun 9, 2023
2 parents 9e3574f + daf83f4 commit d88af20
Show file tree
Hide file tree
Showing 20 changed files with 128 additions and 151 deletions.
6 changes: 3 additions & 3 deletions CRAN-SUBMISSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Version: 0.8.0
Date: 2023-05-09 17:34:27 UTC
SHA: e2f9b361e5cb79eb0faa79faabceb98a4bd1726a
Version: 0.9.0
Date: 2023-06-09 14:22:29 UTC
SHA: 3f6bd1f781851c169a080adb317142b133f58147
4 changes: 3 additions & 1 deletion R/methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,13 @@ c.shapviz <- function(...) {
#' @param ... Arguments passed to `split()`.
#' @returns A "mshapviz" object.
#' @examples
#' \dontrun{
#' dtrain <- xgboost::xgb.DMatrix(data.matrix(iris[, -1]), label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50, nthread = 1)
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 10, nthread = 1)
#' sv <- shapviz(fit, X_pred = dtrain, X = iris)
#' mx <- split(sv, f = iris$Species)
#' sv_dependence(mx, "Petal.Length")
#' }
#' @export
#' @seealso [shapviz()], [rbind.shapviz()]
split.shapviz <- function(x, f, ...) {
Expand Down
49 changes: 24 additions & 25 deletions R/shapviz.R
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
#' scale of the SHAP values.
#' - `S_inter`: Numeric array of SHAP interaction values (or `NULL`).
#' @seealso
#' [sv_importance()], [sv_dependence()], [sv_interaction()],
#' [sv_importance()], [sv_dependence()], [sv_dependence2D()], [sv_interaction()],
#' [sv_waterfall()], [sv_force()], [collapse_shap()]
#' @examples
#' S <- matrix(c(1, -1, -1, 1), ncol = 2, dimnames = list(NULL, c("x", "y")))
Expand Down Expand Up @@ -110,11 +110,11 @@ shapviz.matrix = function(object, X, baseline = 0, collapse = NULL,
#' Creates a "shapviz" object from an XGBoost model.
#' @export
#' @examples
#'
#' \dontrun{
#' # XGBoost models
#' X_pred <- data.matrix(iris[, -1L])
#' dtrain <- xgboost::xgb.DMatrix(X_pred, label = iris[, 1L])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50L, nthread = 1L)
#' X_pred <- data.matrix(iris[, -1])
#' dtrain <- xgboost::xgb.DMatrix(X_pred, label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 10, nthread = 1)
#'
#' # Will use numeric matrix "X_pred" as feature matrix
#' x <- shapviz(fit, X_pred = X_pred)
Expand All @@ -129,25 +129,23 @@ shapviz.matrix = function(object, X, baseline = 0, collapse = NULL,
#' x <- shapviz(fit, X_pred = dtrain, X = iris)
#'
#' # Multiclass setting
#' params <- list(objective = "multi:softprob", num_class = 3L)
#' X_pred <- data.matrix(iris[, -5L])
#' dtrain <- xgboost::xgb.DMatrix(X_pred, label = as.integer(iris[, 5L]) - 1L)
#' fit <- xgboost::xgb.train(
#' params = params, data = dtrain, nrounds = 50L, nthread = 1L
#' )
#' params <- list(objective = "multi:softprob", num_class = 3, nthread = 1)
#' X_pred <- data.matrix(iris[, -5])
#' dtrain <- xgboost::xgb.DMatrix(X_pred, label = as.integer(iris[, 5]) - 1)
#' fit <- xgboost::xgb.train(params = params, data = dtrain, nrounds = 10)
#'
#' # Select specific class
#' x <- shapviz(fit, X_pred = X_pred, which_class = 3L)
#' x <- shapviz(fit, X_pred = X_pred, which_class = 3)
#' x
#'
#' # Or combine all classes to "mshapviz" object
#' x <- shapviz(fit, X_pred = X_pred)
#' x
#'
#' # What if we would have one-hot-encoded values and want to explain the original column?
#' X_pred <- stats::model.matrix(~ . -1, iris[, -1L])
#' dtrain <- xgboost::xgb.DMatrix(X_pred, label = as.integer(iris[, 1L]))
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50L)
#' X_pred <- stats::model.matrix(~ . -1, iris[, -1])
#' dtrain <- xgboost::xgb.DMatrix(X_pred, label = as.integer(iris[, 1]))
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 10, nthread = 1)
#' x <- shapviz(
#' fit,
#' X_pred = X_pred,
Expand All @@ -159,29 +157,30 @@ shapviz.matrix = function(object, X, baseline = 0, collapse = NULL,
#' # Similarly with LightGBM
#' if (requireNamespace("lightgbm", quietly = TRUE)) {
#' fit <- lightgbm::lgb.train(
#' params = list(objective = "regression", num_thread = 1L),
#' data = lightgbm::lgb.Dataset(X_pred, label = iris[, 1L]),
#' nrounds = 50L,
#' verbose = -2L
#' params = list(objective = "regression", num_thread = 1),
#' data = lightgbm::lgb.Dataset(X_pred, label = iris[, 1]),
#' nrounds = 10,
#' verbose = -2
#' )
#'
#' x <- shapviz(fit, X_pred = X_pred)
#' x
#'
#' # Multiclass
#' params <- list(objective = "multiclass", num_class = 3L, num_thread = 1L)
#' X_pred <- data.matrix(iris[, -5L])
#' dtrain <- lightgbm::lgb.Dataset(X_pred, label = as.integer(iris[, 5L]) - 1L)
#' fit <- lightgbm::lgb.train(params = params, data = dtrain, nrounds = 50L)
#' params <- list(objective = "multiclass", num_class = 3, num_thread = 1)
#' X_pred <- data.matrix(iris[, -5])
#' dtrain <- lightgbm::lgb.Dataset(X_pred, label = as.integer(iris[, 5]) - 1)
#' fit <- lightgbm::lgb.train(params = params, data = dtrain, nrounds = 10)
#'
#' # Select specific class
#' x <- shapviz(fit, X_pred = X_pred, which_class = 3L)
#' x <- shapviz(fit, X_pred = X_pred, which_class = 3)
#' x
#'
#' # Or combine all classes to a "mshapviz" object
#' mx <- shapviz(fit, X_pred = X_pred)
#' mx
#' all.equal(mx[[3L]], x)
#' all.equal(mx[[3]], x)
#' }
#' }
shapviz.xgb.Booster = function(object, X_pred, X = X_pred, which_class = NULL,
collapse = NULL, interactions = FALSE, ...) {
Expand Down
15 changes: 6 additions & 9 deletions R/sv_dependence.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,23 @@
#' @param ... Arguments passed to [ggplot2::geom_jitter()].
#' @returns An object of class "ggplot" (or "patchwork") representing a dependence plot.
#' @examples
#' \dontrun{
#' dtrain <- xgboost::xgb.DMatrix(data.matrix(iris[, -1]), label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50, nthread = 1)
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 10, nthread = 1)
#' x <- shapviz(fit, X_pred = dtrain, X = iris)
#' sv_dependence(x, "Petal.Length")
#' sv_dependence(x, "Petal.Length", color_var = "Species")
#' sv_dependence(x, "Petal.Length", color_var = NULL)
#' sv_dependence(x, c("Species", "Petal.Length"))
#' sv_dependence(x, "Petal.Width", color_var = c("Species", "Petal.Length"))
#'
#' # SHAP interaction values
#' # SHAP interaction values/main effects
#' x2 <- shapviz(fit, X_pred = dtrain, X = iris, interactions = TRUE)
#' sv_dependence(x2, "Petal.Length", interactions = TRUE)
#' sv_dependence(x2, c("Petal.Length", "Species"), color_var = NULL, interactions = TRUE)
#'
#' # Show main effect of "Petal.Length" for setosa and virginica separately
#' mx <- c(
#' setosa = x2[x2$X$Species == "setosa"],
#' virginica = x2[x2$X$Species == "virginica"]
#' sv_dependence(
#' x2, c("Petal.Length", "Species"), color_var = NULL, interactions = TRUE
#' )
#' sv_dependence(mx, "Petal.Length", color_var = NULL, interactions = TRUE)
#' }
#' @export
#' @seealso [potential_interactions()]
sv_dependence <- function(object, ...) {
Expand Down
8 changes: 3 additions & 5 deletions R/sv_dependence2D.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,12 @@
#' @param ... Arguments passed to [ggplot2::geom_jitter()].
#' @returns An object of class "ggplot" (or "patchwork") representing a dependence plot.
#' @examples
#' \dontrun{
#' dtrain <- xgboost::xgb.DMatrix(data.matrix(iris[, -1]), label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50, nthread = 1)
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 10, nthread = 1)
#' sv <- shapviz(fit, X_pred = dtrain, X = iris)
#' sv_dependence2D(sv, x = "Petal.Length", y = "Species")
#' sv_dependence2D(sv, x = "Petal.Length", y = "Sepal.Width")
#' sv_dependence2D(sv, x = c("Petal.Length", "Species"), y = "Sepal.Width")
#' sv_dependence2D(
#' sv, x = c("Petal.Length", "Species"), y = c("Petal.Width", "Sepal.Width")
#' )
#'
#' # SHAP interaction values
#' sv2 <- shapviz(fit, X_pred = dtrain, X = iris, interactions = TRUE)
Expand All @@ -48,6 +45,7 @@
#' # mshapviz object
#' mx <- split(sv, f = iris$Species)
#' sv_dependence2D(mx, x = "Petal.Length", y = "Sepal.Width")
#' }
#' @export
#' @seealso [sv_dependence()]
sv_dependence2D <- function(object, ...) {
Expand Down
7 changes: 3 additions & 4 deletions R/sv_force.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@
#' (via [ggrepel::geom_text_repel()]).
#' @returns An object of class "ggplot" (or "patchwork") representing a force plot.
#' @examples
#' \dontrun{
#' dtrain <- xgboost::xgb.DMatrix(data.matrix(iris[, -1]), label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50, nthread = 1)
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 20, nthread = 1)
#' x <- shapviz(fit, X_pred = dtrain, X = iris[, -1])
#' sv_force(x)
#' sv_force(x, row_id = 65, max_display = 3, size = 9, fill_colors = 4:5)
#'
#' # Aggregate over all observations with Petal.Length == 1.4
#' sv_force(x, row_id = x$X$Petal.Length == 1.4)
#'
#' # Combine two force plots via {patchwork}
#' sv_force(c(Obs1 = x[1], Obs2 = x[2]))
#' }
#' @export
#' @seealso [sv_waterfall()]
sv_force <- function(object, ...) {
Expand Down
11 changes: 4 additions & 7 deletions R/sv_importance.R
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,16 @@
#' `kind = "no"` - a named numeric vector of sorted SHAP feature importances
#' (or a list of such vectors in case of an object of class "mshapviz").
#' @examples
#' \dontrun{
#' X_train <- data.matrix(iris[, -1])
#' dtrain <- xgboost::xgb.DMatrix(X_train, label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50, nthread = 1)
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 10, nthread = 1)
#' x <- shapviz(fit, X_pred = X_train)
#' sv_importance(x)
#' sv_importance(x, kind = "beeswarm", show_numbers = TRUE)
#' sv_importance(x, kind = "no")
#' sv_importance(x, kind = "beeswarm", show_numbers = TRUE)
#' }
#'
#' X <- data.frame(matrix(rnorm(1000), ncol = 20))
#' S <- as.matrix(X)
#' x2 <- shapviz(S, X)
#' sv_importance(x2)
#' sv_importance(x2, max_display = 5)
#' @seealso \code{\link{sv_interaction}}
#' @export
sv_importance <- function(object, ...) {
Expand Down
7 changes: 4 additions & 3 deletions R/sv_interaction.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
#' numeric matrix of average absolute SHAP interactions sorted by the average
#' absolute SHAP values (or a list of such matrices in case of "mshapviz" object).
#' @examples
#' \dontrun{
#' dtrain <- xgboost::xgb.DMatrix(data.matrix(iris[, -1]), label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50, nthread = 1)
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 10, nthread = 1)
#' x <- shapviz(fit, X_pred = dtrain, X = iris, interactions = TRUE)
#' sv_interaction(x)
#' sv_interaction(x, max_display = 2, size = 3, alpha = 0.1)
#' sv_interaction(x, kind = "no")
#' sv_interaction(x, max_display = 2, size = 3)
#' }
#' @seealso [sv_importance()]
#' @export
sv_interaction <- function(object, ...) {
Expand Down
14 changes: 3 additions & 11 deletions R/sv_waterfall.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
#' will altogether suppress adding text to the bars.
#' @returns An object of class "ggplot" (or "patchwork") representing a waterfall plot.
#' @examples
#' \dontrun{
#' dtrain <- xgboost::xgb.DMatrix(data.matrix(iris[, -1]), label = iris[, 1])
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 50, nthread = 1)
#' fit <- xgboost::xgb.train(data = dtrain, nrounds = 20, nthread = 1)
#' x <- shapviz(fit, X_pred = dtrain, X = iris[, -1])
#' sv_waterfall(x)
#' sv_waterfall(x, row_id = 123, max_display = 2, size = 9, fill_colors = 4:5)
Expand All @@ -48,16 +49,7 @@
#'
#' # Aggregate over all observations with Petal.Length == 1.4
#' sv_waterfall(x, row_id = x$X$Petal.Length == 1.4)
#'
#' # More features
#' X <- as.data.frame(matrix(1:100, nrow = 10))
#' S <- as.matrix(X)
#' shp <- shapviz(S, X)
#' sv_waterfall(shp)
#'
#' # Combine two waterfall plots via {patchwork}
#' sv_waterfall(c(Obs1 = x[1], Obs2 = x[2])) +
#' patchwork::plot_layout(ncol = 1)
#' }
#' @export
#' @seealso [sv_force()]
sv_waterfall <- function(object, ...) {
Expand Down
35 changes: 21 additions & 14 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# Re-resubmission

Examples that take 0.09 seconds on my Windows laptop take 6 seconds on Linux. I don't know how to fix this, so I am resorting to dontruns around all examples involving XGBoost.

# Re-resubmission

Examples still taking too long on Linux. No idea how to fix this except using dontruns...

# Resubmission

Examples taking too long on Linux.

- I have now reduced the number of examples.
- And the number of boosting rounds.

# shapviz 0.9.0

Hello CRAN team
Expand All @@ -8,29 +23,21 @@ Hello CRAN team

## Checks look good

### check(manual = TRUE, cran = TRUE)

> checking data for ASCII and uncompressed saves ... OK
WARNING
'qpdf' is needed for checks on size reduction of PDFs
### check(manual = TRUE, cran = TRUE)

> checking HTML version of manual ... NOTE
Skipping checking HTML validation: no command 'tidy' found

### check_rhub(): Some usual notes...
### RHub

* checking package dependencies ... NOTE
Packages which this enhances but not available for checking:
'fastshap', 'h2o', 'lightgbm'
* checking HTML version of manual ... NOTE
Skipping checking HTML validation: no command 'tidy' found
Skipping checking math rendering: package 'V8' unavailable
* checking for non-standard things in the check directory ... NOTE
Found the following files/directories:
''NULL''
* checking for detritus in the temp directory ... NOTE
Found the following files/directories:
'lastMiKTeXException'

### check_win_devel()


### Winbuilder()

Status: OK
Loading

0 comments on commit d88af20

Please sign in to comment.