From 660d751e2b51749459d0eaf79c7d45667970a56b Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Fri, 10 Nov 2023 15:33:44 +0100 Subject: [PATCH 1/3] Preparation of CRAN release --- NAMESPACE | 1 + R/kernelshap.R | 2 +- R/methods.R | 50 ++++++++++++++++++++--------- R/permshap.R | 2 +- README.md | 2 +- cran-comments.md | 60 ++++++----------------------------- man/print.kernelshap.Rd | 14 ++------ man/print.permshap.Rd | 29 +++++++++++++++++ man/summary.kernelshap.Rd | 12 +++---- man/summary.permshap.Rd | 31 ++++++++++++++++++ packaging.R | 2 -- revdep/README.md | 4 +-- tests/testthat/test-methods.R | 10 ++++-- 13 files changed, 125 insertions(+), 94 deletions(-) create mode 100644 man/print.permshap.Rd create mode 100644 man/summary.permshap.Rd diff --git a/NAMESPACE b/NAMESPACE index a008615..be68ddf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,6 +9,7 @@ S3method(permshap,ranger) S3method(print,kernelshap) S3method(print,permshap) S3method(summary,kernelshap) +S3method(summary,permshap) export(is.kernelshap) export(is.permshap) export(kernelshap) diff --git a/R/kernelshap.R b/R/kernelshap.R index 7d69312..6e5b84c 100644 --- a/R/kernelshap.R +++ b/R/kernelshap.R @@ -165,7 +165,7 @@ #' s #' #' # MODEL TWO: Multi-response linear regression -#' fit <- lm(as.matrix(iris[1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) +#' fit <- lm(as.matrix(iris[, 1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) #' s <- kernelshap(fit, iris[1:4, 3:5], bg_X = bg_X) #' summary(s) #' diff --git a/R/methods.R b/R/methods.R index 7ee5ed1..a488459 100644 --- a/R/methods.R +++ b/R/methods.R @@ -1,6 +1,4 @@ -#' Print Method -#' -#' Prints the first two rows of the matrix (or matrices) of SHAP values. +#' Prints "kernelshap" Object #' #' @param x An object of class "kernelshap". #' @param n Maximum number of rows of SHAP values to print. @@ -8,8 +6,8 @@ #' @returns Invisibly, the input is returned. #' @export #' @examples -#' fit <- stats::lm(Sepal.Length ~ ., data = iris) -#' s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[-1]) +#' fit <- lm(Sepal.Length ~ ., data = iris) +#' s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[, -1]) #' s #' @seealso [kernelshap()] print.kernelshap <- function(x, n = 2L, ...) { @@ -18,25 +16,32 @@ print.kernelshap <- function(x, n = 2L, ...) { invisible(x) } -#' @describeIn print.kernelshap Print method for "permshap" object +#' Prints "permshap" Object +#' +#' @param x An object of class "permshap". +#' @inheritParams print.kernelshap +#' @inherit print.kernelshap return #' @export +#' @examples +#' fit <- lm(Sepal.Length ~ ., data = iris) +#' s <- permshap(fit, iris[1:3, -1], bg_X = iris[, -1]) +#' s +#' @seealso [permshap()] print.permshap <- function(x, n = 2L, ...) { print.kernelshap(x, n = n, ...) } -#' Summary Method +#' Summarizes "kernelshap" Object #' #' @param object An object of class "kernelshap". -#' @param compact Set to `TRUE` to hide printing the top n SHAP values, -#' standard errors and feature values. -#' @param n Maximum number of rows of SHAP values, standard errors and feature values -#' to print. +#' @param compact Set to `TRUE` for a more compact summary. +#' @param n Maximum number of rows of SHAP values etc. to print. #' @param ... Further arguments passed from other methods. #' @returns Invisibly, the input is returned. #' @export #' @examples -#' fit <- stats::lm(Sepal.Length ~ ., data = iris) -#' s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[-1]) +#' fit <- lm(Sepal.Length ~ ., data = iris) +#' s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[, -1]) #' summary(s) #' @seealso [kernelshap()] summary.kernelshap <- function(object, compact = FALSE, n = 2L, ...) { @@ -74,6 +79,21 @@ summary.kernelshap <- function(object, compact = FALSE, n = 2L, ...) { invisible(object) } +#' Summarizes "permshap" Object +#' +#' @param object An object of class "permshap". +#' @inheritParams summary.kernelshap +#' @inherit summary.kernelshap return +#' @export +#' @examples +#' fit <- lm(Sepal.Length ~ ., data = iris) +#' s <- permshap(fit, iris[1:3, -1], bg_X = iris[, -1]) +#' summary(s) +#' @seealso [permshap()] +summary.permshap <- function(object, compact = FALSE, n = 2L, ...) { + summary.kernelshap(object, compact = compact, n = n, ...) +} + #' Check for kernelshap #' #' Is object of class "kernelshap"? @@ -83,7 +103,7 @@ summary.kernelshap <- function(object, compact = FALSE, n = 2L, ...) { #' @export #' @examples #' fit <- lm(Sepal.Length ~ ., data = iris) -#' s <- kernelshap(fit, iris[1:2, -1], bg_X = iris[-1]) +#' s <- kernelshap(fit, iris[1:2, -1], bg_X = iris[, -1]) #' is.kernelshap(s) #' is.kernelshap("a") #' @seealso [kernelshap()] @@ -100,7 +120,7 @@ is.kernelshap <- function(object){ #' @export #' @examples #' fit <- lm(Sepal.Length ~ ., data = iris) -#' s <- permshap(fit, iris[1:2, -1], bg_X = iris[-1]) +#' s <- permshap(fit, iris[1:2, -1], bg_X = iris[, -1]) #' is.permshap(s) #' is.permshap("a") #' @seealso [kernelshap()] diff --git a/R/permshap.R b/R/permshap.R index 0cc79e7..6fd6202 100644 --- a/R/permshap.R +++ b/R/permshap.R @@ -33,7 +33,7 @@ #' s #' #' # MODEL TWO: Multi-response linear regression -#' fit <- lm(as.matrix(iris[1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) +#' fit <- lm(as.matrix(iris[, 1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) #' s <- permshap(fit, iris[1:4, 3:5], bg_X = bg_X) #' s #' diff --git a/README.md b/README.md index 7a7829c..c4a4aab 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The package contains two workhorses to calculate SHAP values for any model: ### Kernel SHAP or permutation SHAP? -- Exact Kernel SHAP and exact permutation SHAP values agree for additive models, and differ for models with interactions. +- Exact Kernel SHAP and exact permutation SHAP values (usually) agree for additive models. - If the number of features is sufficiently small, we recommend `permshap()` over `kernelshap()`. ### Typical workflow to explain any model diff --git a/cran-comments.md b/cran-comments.md index 3f878b1..bbe0100 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,46 +1,10 @@ -# Resubmission II +# kernelshap 0.4.0 -I have now removed the non-registered DOI from the description file. +Dear CRAN-team -This was Uwe's comment: +I have added exact permutation SHAP values, and the possibility to use factor-valued predictions. - Found the following (possibly) invalid DOIs: - DOI: 10.5555/3295222.3295230 - From: DESCRIPTION - Status: 404 - Message: Not Found - -and looking for the DOI shows it is not registered. -Even when going to -https://dl.acm.org/doi/10.5555/3295222.3295230 -and clicking on the "Publisher Site" link leads us into nirvana. - -So I guess the is ill registered and you have to revert the change. My -apologoies, I had not checked whether the DOI given is registreed or not. - -Best, - - -# Resubmission I - -I stumbled over a DOI: Uwe gently pointed this out: - -" - The Description field contains - , and Covert and Lee - Please use permanent DOI markup for linking to publications as in -. -" - -This resubmission fixes this. - -# Original message - -Hello CRAN - -This is a small maintenance release only. - -Thanks a lot +Thanks a lot for running CRAN. Michael @@ -48,28 +12,22 @@ Michael ### Revdep -survex 1.1.3 +survex 1.2.0 - OK: 1 - BROKEN: 0 -### Local check with innocent NOTE +### Local check with usual NOTE -❯ checking HTML version of manual ... NOTE +checking HTML version of manual ... NOTE Skipping checking HTML validation: no command 'tidy' found ### `check_win_devel()` NOTE -- R Under development (unstable) (2023-09-11 r85126 ucrt) +- R Under development (unstable) (2023-11-09 r85497 ucrt) ### `check_rhub()` NOTES --> Note sure where the 403 problem comes from. Is it relevant? - -Found the following (possibly) invalid URLs: - URL: https://dl.acm.org/doi/10.5555/3295222.3295230 - From: DESCRIPTION - Status: 403 - Message: Forbidden * checking HTML version of manual ... NOTE Skipping checking HTML validation: no command 'tidy' found Skipping checking math rendering: package 'V8' unavailable + diff --git a/man/print.kernelshap.Rd b/man/print.kernelshap.Rd index e4e4826..e3d43f0 100644 --- a/man/print.kernelshap.Rd +++ b/man/print.kernelshap.Rd @@ -2,12 +2,9 @@ % Please edit documentation in R/methods.R \name{print.kernelshap} \alias{print.kernelshap} -\alias{print.permshap} -\title{Print Method} +\title{Prints "kernelshap" Object} \usage{ \method{print}{kernelshap}(x, n = 2L, ...) - -\method{print}{permshap}(x, n = 2L, ...) } \arguments{ \item{x}{An object of class "kernelshap".} @@ -20,15 +17,10 @@ Invisibly, the input is returned. } \description{ -Prints the first two rows of the matrix (or matrices) of SHAP values. +Prints "kernelshap" Object } -\section{Functions}{ -\itemize{ -\item \code{print(permshap)}: Print method for "permshap" object - -}} \examples{ -fit <- stats::lm(Sepal.Length ~ ., data = iris) +fit <- lm(Sepal.Length ~ ., data = iris) s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[-1]) s } diff --git a/man/print.permshap.Rd b/man/print.permshap.Rd new file mode 100644 index 0000000..17bcd59 --- /dev/null +++ b/man/print.permshap.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods.R +\name{print.permshap} +\alias{print.permshap} +\title{Prints "permshap" Object} +\usage{ +\method{print}{permshap}(x, n = 2L, ...) +} +\arguments{ +\item{x}{An object of class "permshap".} + +\item{n}{Maximum number of rows of SHAP values to print.} + +\item{...}{Further arguments passed from other methods.} +} +\value{ +Invisibly, the input is returned. +} +\description{ +Prints "permshap" Object +} +\examples{ +fit <- lm(Sepal.Length ~ ., data = iris) +s <- permshap(fit, iris[1:3, -1], bg_X = iris[-1]) +s +} +\seealso{ +\code{\link[=permshap]{permshap()}} +} diff --git a/man/summary.kernelshap.Rd b/man/summary.kernelshap.Rd index df743e0..df43974 100644 --- a/man/summary.kernelshap.Rd +++ b/man/summary.kernelshap.Rd @@ -2,18 +2,16 @@ % Please edit documentation in R/methods.R \name{summary.kernelshap} \alias{summary.kernelshap} -\title{Summary Method} +\title{Summarizes "kernelshap" Object} \usage{ \method{summary}{kernelshap}(object, compact = FALSE, n = 2L, ...) } \arguments{ \item{object}{An object of class "kernelshap".} -\item{compact}{Set to \code{TRUE} to hide printing the top n SHAP values, -standard errors and feature values.} +\item{compact}{Set to \code{TRUE} for a more compact summary.} -\item{n}{Maximum number of rows of SHAP values, standard errors and feature values -to print.} +\item{n}{Maximum number of rows of SHAP values etc. to print.} \item{...}{Further arguments passed from other methods.} } @@ -21,10 +19,10 @@ to print.} Invisibly, the input is returned. } \description{ -Summary Method +Summarizes "kernelshap" Object } \examples{ -fit <- stats::lm(Sepal.Length ~ ., data = iris) +fit <- lm(Sepal.Length ~ ., data = iris) s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[-1]) summary(s) } diff --git a/man/summary.permshap.Rd b/man/summary.permshap.Rd new file mode 100644 index 0000000..016a77d --- /dev/null +++ b/man/summary.permshap.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods.R +\name{summary.permshap} +\alias{summary.permshap} +\title{Summarizes "permshap" Object} +\usage{ +\method{summary}{permshap}(object, compact = FALSE, n = 2L, ...) +} +\arguments{ +\item{object}{An object of class "permshap".} + +\item{compact}{Set to \code{TRUE} for a more compact summary.} + +\item{n}{Maximum number of rows of SHAP values etc. to print.} + +\item{...}{Further arguments passed from other methods.} +} +\value{ +Invisibly, the input is returned. +} +\description{ +Summarizes "permshap" Object +} +\examples{ +fit <- lm(Sepal.Length ~ ., data = iris) +s <- permshap(fit, iris[1:3, -1], bg_X = iris[-1]) +summary(s) +} +\seealso{ +\code{\link[=permshap]{permshap()}} +} diff --git a/packaging.R b/packaging.R index 8f0358f..fd900bb 100644 --- a/packaging.R +++ b/packaging.R @@ -93,8 +93,6 @@ build() # build(binary = TRUE) install(upgrade = FALSE) -# pkgdown::build_site(run_dont_run = TRUE) - # Run only if package is public(!) and should go to CRAN if (FALSE) { check_win_devel() diff --git a/revdep/README.md b/revdep/README.md index 2d9a88b..34e949d 100644 --- a/revdep/README.md +++ b/revdep/README.md @@ -10,7 +10,7 @@ |collate |German_Switzerland.utf8 | |ctype |German_Switzerland.utf8 | |tz |Europe/Zurich | -|date |2023-09-12 | +|date |2023-11-10 | |rstudio |2023.06.1+524 Mountain Hydrangea (desktop) | |pandoc |3.1.6 @ C:\Users\Michael\AppData\Local\Pandoc\pandoc.exe | @@ -18,7 +18,7 @@ |package |old |new |Δ | |:----------|:------|:------|:--| -|kernelshap |0.3.7 |0.3.8 |* | +|kernelshap |0.3.8 |0.4.0 |* | |foreach |1.5.2 |1.5.2 | | |iterators |1.0.14 |1.0.14 | | diff --git a/tests/testthat/test-methods.R b/tests/testthat/test-methods.R index fa95ebc..ac99603 100644 --- a/tests/testthat/test-methods.R +++ b/tests/testthat/test-methods.R @@ -1,5 +1,8 @@ fit <- lm(Sepal.Length ~ ., data = iris) -s <- kernelshap(fit, iris[1:2, -1L], bg_X = iris[-1L], verbose = FALSE) +set.seed(1) +s <- kernelshap( + fit, iris[1:2, -1L], bg_X = iris[-1L], verbose = FALSE, exact = FALSE, hybrid_degree = 1 +) test_that("is.kernelshap() works", { expect_true(is.kernelshap(s)) @@ -19,6 +22,7 @@ test_that("is.permshap() works", { expect_false(is.permshap(1)) }) -test_that("print() also works for permshap", { +test_that("print() and summary() also works for permshap", { capture_output(expect_no_error(print(s))) -}) \ No newline at end of file + capture_output(expect_no_error(summary(s))) +}) From 4b25bb0b9f2223185eac1fe01a19d6014d01eb12 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Fri, 10 Nov 2023 15:39:41 +0100 Subject: [PATCH 2/3] Update documentation --- R/kernelshap.R | 2 +- man/is.kernelshap.Rd | 2 +- man/is.permshap.Rd | 2 +- man/kernelshap.Rd | 4 ++-- man/permshap.Rd | 4 ++-- man/print.kernelshap.Rd | 2 +- man/print.permshap.Rd | 2 +- man/summary.kernelshap.Rd | 2 +- man/summary.permshap.Rd | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/R/kernelshap.R b/R/kernelshap.R index 6e5b84c..2a58895 100644 --- a/R/kernelshap.R +++ b/R/kernelshap.R @@ -117,7 +117,7 @@ #' see README for an example. Parallelization automatically disables the progress bar. #' @param parallel_args Named list of arguments passed to [foreach::foreach()]. #' Ideally, this is `NULL` (default). Only relevant if `parallel = TRUE`. -#' Example on Windows: if `object` is a GAM fitted with package {mgcv}, +#' Example on Windows: if `object` is a GAM fitted with package 'mgcv', #' then one might need to set `parallel_args = list(.packages = "mgcv")`. #' @param verbose Set to `FALSE` to suppress messages and the progress bar. #' @param ... Additional arguments passed to `pred_fun(object, X, ...)`. diff --git a/man/is.kernelshap.Rd b/man/is.kernelshap.Rd index a6aa0d1..2be9805 100644 --- a/man/is.kernelshap.Rd +++ b/man/is.kernelshap.Rd @@ -17,7 +17,7 @@ Is object of class "kernelshap"? } \examples{ fit <- lm(Sepal.Length ~ ., data = iris) -s <- kernelshap(fit, iris[1:2, -1], bg_X = iris[-1]) +s <- kernelshap(fit, iris[1:2, -1], bg_X = iris[, -1]) is.kernelshap(s) is.kernelshap("a") } diff --git a/man/is.permshap.Rd b/man/is.permshap.Rd index f7dcada..b73fd6d 100644 --- a/man/is.permshap.Rd +++ b/man/is.permshap.Rd @@ -17,7 +17,7 @@ Is object of class "permshap"? } \examples{ fit <- lm(Sepal.Length ~ ., data = iris) -s <- permshap(fit, iris[1:2, -1], bg_X = iris[-1]) +s <- permshap(fit, iris[1:2, -1], bg_X = iris[, -1]) is.permshap(s) is.permshap("a") } diff --git a/man/kernelshap.Rd b/man/kernelshap.Rd index 8d57c56..adbd6bc 100644 --- a/man/kernelshap.Rd +++ b/man/kernelshap.Rd @@ -143,7 +143,7 @@ see README for an example. Parallelization automatically disables the progress b \item{parallel_args}{Named list of arguments passed to \code{\link[foreach:foreach]{foreach::foreach()}}. Ideally, this is \code{NULL} (default). Only relevant if \code{parallel = TRUE}. -Example on Windows: if \code{object} is a GAM fitted with package {mgcv}, +Example on Windows: if \code{object} is a GAM fitted with package 'mgcv', then one might need to set \code{parallel_args = list(.packages = "mgcv")}.} \item{verbose}{Set to \code{FALSE} to suppress messages and the progress bar.} @@ -257,7 +257,7 @@ s <- kernelshap(fit, X_explain, bg_X = bg_X) s # MODEL TWO: Multi-response linear regression -fit <- lm(as.matrix(iris[1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) +fit <- lm(as.matrix(iris[, 1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) s <- kernelshap(fit, iris[1:4, 3:5], bg_X = bg_X) summary(s) diff --git a/man/permshap.Rd b/man/permshap.Rd index 75d383e..1fd2d4c 100644 --- a/man/permshap.Rd +++ b/man/permshap.Rd @@ -81,7 +81,7 @@ see README for an example. Parallelization automatically disables the progress b \item{parallel_args}{Named list of arguments passed to \code{\link[foreach:foreach]{foreach::foreach()}}. Ideally, this is \code{NULL} (default). Only relevant if \code{parallel = TRUE}. -Example on Windows: if \code{object} is a GAM fitted with package {mgcv}, +Example on Windows: if \code{object} is a GAM fitted with package 'mgcv', then one might need to set \code{parallel_args = list(.packages = "mgcv")}.} \item{verbose}{Set to \code{FALSE} to suppress messages and the progress bar.} @@ -130,7 +130,7 @@ s <- permshap(fit, X_explain, bg_X = bg_X) s # MODEL TWO: Multi-response linear regression -fit <- lm(as.matrix(iris[1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) +fit <- lm(as.matrix(iris[, 1:2]) ~ Petal.Length + Petal.Width + Species, data = iris) s <- permshap(fit, iris[1:4, 3:5], bg_X = bg_X) s diff --git a/man/print.kernelshap.Rd b/man/print.kernelshap.Rd index e3d43f0..0b63815 100644 --- a/man/print.kernelshap.Rd +++ b/man/print.kernelshap.Rd @@ -21,7 +21,7 @@ Prints "kernelshap" Object } \examples{ fit <- lm(Sepal.Length ~ ., data = iris) -s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[-1]) +s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[, -1]) s } \seealso{ diff --git a/man/print.permshap.Rd b/man/print.permshap.Rd index 17bcd59..a01817d 100644 --- a/man/print.permshap.Rd +++ b/man/print.permshap.Rd @@ -21,7 +21,7 @@ Prints "permshap" Object } \examples{ fit <- lm(Sepal.Length ~ ., data = iris) -s <- permshap(fit, iris[1:3, -1], bg_X = iris[-1]) +s <- permshap(fit, iris[1:3, -1], bg_X = iris[, -1]) s } \seealso{ diff --git a/man/summary.kernelshap.Rd b/man/summary.kernelshap.Rd index df43974..c7f0d3a 100644 --- a/man/summary.kernelshap.Rd +++ b/man/summary.kernelshap.Rd @@ -23,7 +23,7 @@ Summarizes "kernelshap" Object } \examples{ fit <- lm(Sepal.Length ~ ., data = iris) -s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[-1]) +s <- kernelshap(fit, iris[1:3, -1], bg_X = iris[, -1]) summary(s) } \seealso{ diff --git a/man/summary.permshap.Rd b/man/summary.permshap.Rd index 016a77d..10880e7 100644 --- a/man/summary.permshap.Rd +++ b/man/summary.permshap.Rd @@ -23,7 +23,7 @@ Summarizes "permshap" Object } \examples{ fit <- lm(Sepal.Length ~ ., data = iris) -s <- permshap(fit, iris[1:3, -1], bg_X = iris[-1]) +s <- permshap(fit, iris[1:3, -1], bg_X = iris[, -1]) summary(s) } \seealso{ From 4478f177f13b2315ad60f497374fe65c999d1f41 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Fri, 10 Nov 2023 21:24:18 +0100 Subject: [PATCH 3/3] Accepted --- CRAN-SUBMISSION | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION index ee58be4..492dc85 100644 --- a/CRAN-SUBMISSION +++ b/CRAN-SUBMISSION @@ -1,3 +1,3 @@ -Version: 0.3.8 -Date: 2023-09-23 12:06:38 UTC -SHA: 7ca4f7e46e925abd8cf0155227d126ebd9ea2364 +Version: 0.4.0 +Date: 2023-11-10 18:24:23 UTC +SHA: 4b25bb0b9f2223185eac1fe01a19d6014d01eb12