From 68230bdf48e13810435e19b1651ba6831e3904f6 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Fri, 10 Jan 2025 15:00:59 -0800 Subject: [PATCH] move ggplot2 to enhances - several other tweaks too --- DESCRIPTION | 6 +- NAMESPACE | 1 + R/geom_parttree.R | 104 +++++++++++++++++------------------ man/geom_parttree.Rd | 27 +++++---- vignettes/parttree-art.Rmd | 6 +- vignettes/parttree-intro.Rmd | 6 +- 6 files changed, 81 insertions(+), 69 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5167d69..328406d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -38,8 +38,9 @@ Imports: partykit, rlang, rpart, - ggplot2 (>= 3.4.0), - tinyplot (> 0.1.0) + tinyplot (>= 0.2.0) +Enhances: + ggplot2 (>= 3.4.0) Suggests: tinytest, tinysnapshot (>= 0.0.3), @@ -55,5 +56,4 @@ Suggests: imager, knitr, rmarkdown -Remotes: grantmcdermott/tinyplot VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 601e6f6..18e0a04 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -15,3 +15,4 @@ importFrom(data.table,fifelse) importFrom(graphics,par) importFrom(stats,reformulate) importFrom(tinyplot,tinyplot) +importFrom(utils,packageVersion) diff --git a/R/geom_parttree.R b/R/geom_parttree.R index 5754015..1d48606 100644 --- a/R/geom_parttree.R +++ b/R/geom_parttree.R @@ -1,10 +1,10 @@ -#' @title Visualise tree partitions with ggplot2 +#' @title Visualize tree partitions with ggplot2 #' -#' @description `geom_parttree()` is a simple extension of -#' [ggplot2::geom_rect()]that first calls -#' [parttree()] to convert the inputted tree object into an -#' amenable data frame. Please note that `ggplot2` is not a hard dependency -#' of `parttree` and should thus be installed separately on the user's system. +#' @description `geom_parttree()` is a simple wrapper around [parttree()] that +#' takes a tree model object and then converts into an amenable data frame +#' that `ggplot2` knows how to plot. Please note that `ggplot2` is not a hard +#' dependency of `parttree` and must thus be installed separately on the +#' user's system before calling `geom_parttree`. #' @param data An [rpart::rpart.object] or an object of compatible #' type (e.g. a decision tree constructed via the `partykit`, `tidymodels`, or #' `mlr3` front-ends). @@ -36,12 +36,12 @@ #' \item{\code{size}} #' } #' -#' @seealso [parttree()], [ggplot2::geom_rect()]. -#' @export #' @examples +#' # install.packages("ggplot2") +#' library(ggplot2) # ggplot2 must be installed/loaded separately +#' #' library(parttree) # this package #' library(rpart) # decision trees -#' library(ggplot2) # ggplot2 must be loaded separately #' #' ### Simple decision tree (max of two predictor variables) #' @@ -74,12 +74,12 @@ #' #' ### Various front-end frameworks are also supported, e.g.: #' +#' # install.packages("parsnip") #' library(parsnip) #' -#' iris_tree_parsnip = -#' decision_tree() %>% -#' set_engine("rpart") %>% -#' set_mode("classification") %>% +#' iris_tree_parsnip = decision_tree() |> +#' set_engine("rpart") |> +#' set_mode("classification") |> #' fit(Species ~ Petal.Length + Petal.Width, data=iris) #' #' p + geom_parttree(data = iris_tree_parsnip, aes(fill=Species), alpha = 0.1) @@ -103,49 +103,49 @@ #' #' ## Better to scale fill to the original data #' p3 + scale_fill_continuous(limits = range(iris$Petal.Length)) -geom_parttree = - function(mapping = NULL, data = NULL, - stat = "identity", position = "identity", - linejoin = "mitre", na.rm = FALSE, show.legend = NA, - inherit.aes = TRUE, flip = FALSE, ...) { +#' +#' @seealso [plot.parttree()], which provides an alternative plotting method using base R graphics. +#' @importFrom utils packageVersion +#' @export +geom_parttree = function( + mapping = NULL, data = NULL, + stat = "identity", position = "identity", + linejoin = "mitre", na.rm = FALSE, show.legend = NA, + inherit.aes = TRUE, flip = FALSE, ... + ) { ggplot2_installed = requireNamespace("ggplot2", quietly = TRUE) if (isFALSE(ggplot2_installed)) { stop("Please install the ggplot2 package.", .call = FALSE) - } else if (utils::packageVersion("ggplot2") < "3.4.0") { + } else if (packageVersion("ggplot2") < "3.4.0") { stop("Please install a newer version of ggplot2 (>= 3.4.0).") - } - - - pdata = parttree(data, flip = flip) - mapping_null = is.null(mapping) - mapping$xmin = quote(xmin) - mapping$xmax = quote(xmax) - mapping$ymin = quote(ymin) - mapping$ymax = quote(ymax) - if (mapping_null) { - mapping = ggplot2::aes_all(mapping) - } - mapping$x = rlang::quo(NULL) - mapping$y = rlang::quo(NULL) - ggplot2::layer( - stat = stat, geom = GeomParttree, - data = pdata, - mapping = mapping, - position = position, show.legend = show.legend, inherit.aes = inherit.aes, - params = list(na.rm = na.rm, ...) + } else { + ## Underlying ggproto object + GeomParttree = ggplot2::ggproto( + "GeomParttree", ggplot2::GeomRect, + default_aes = ggplot2::aes( + colour = "black", linewidth = 0.5, linetype = 1, + x=NULL, y = NULL, fill = NA, alpha = NA + ), + non_missing_aes = c("x", "y", "xmin", "xmax", "ymin", "ymax") ) + pdata = parttree(data, flip = flip) + mapping_null = is.null(mapping) + mapping$xmin = quote(xmin) + mapping$xmax = quote(xmax) + mapping$ymin = quote(ymin) + mapping$ymax = quote(ymax) + if (mapping_null) { + mapping = ggplot2::aes_all(mapping) + } + mapping$x = rlang::quo(NULL) + mapping$y = rlang::quo(NULL) + ggplot2::layer( + stat = stat, geom = GeomParttree, + data = pdata, + mapping = mapping, + position = position, show.legend = show.legend, inherit.aes = inherit.aes, + params = list(na.rm = na.rm, ...) + ) + } } - -## Underlying ggproto object -GeomParttree = - ggplot2::ggproto( - "GeomParttree", ggplot2::GeomRect, - default_aes = ggplot2::aes(colour = "black", linewidth = 0.5, linetype = 1, - x=NULL, y = NULL, - fill = NA, alpha = NA - ), - non_missing_aes = c("x", "y", "xmin", "xmax", "ymin", "ymax") - ) - - diff --git a/man/geom_parttree.Rd b/man/geom_parttree.Rd index cf30bb3..8a99b1c 100644 --- a/man/geom_parttree.Rd +++ b/man/geom_parttree.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/geom_parttree.R \name{geom_parttree} \alias{geom_parttree} -\title{Visualise tree partitions with ggplot2} +\title{Visualize tree partitions with ggplot2} \usage{ geom_parttree( mapping = NULL, @@ -104,11 +104,11 @@ lists which parameters it can accept. }} } \description{ -\code{geom_parttree()} is a simple extension of -\code{\link[ggplot2:geom_tile]{ggplot2::geom_rect()}}that first calls -\code{\link[=parttree]{parttree()}} to convert the inputted tree object into an -amenable data frame. Please note that \code{ggplot2} is not a hard dependency -of \code{parttree} and should thus be installed separately on the user's system. +\code{geom_parttree()} is a simple wrapper around \code{\link[=parttree]{parttree()}} that +takes a tree model object and then converts into an amenable data frame +that \code{ggplot2} knows how to plot. Please note that \code{ggplot2} is not a hard +dependency of \code{parttree} and must thus be installed separately on the +user's system before calling \code{geom_parttree}. } \details{ Because of the way that \code{ggplot2} validates inputs and assembles @@ -135,9 +135,11 @@ cue regarding the prediction in each partition region)} } \examples{ +# install.packages("ggplot2") +library(ggplot2) # ggplot2 must be installed/loaded separately + library(parttree) # this package library(rpart) # decision trees -library(ggplot2) # ggplot2 must be loaded separately ### Simple decision tree (max of two predictor variables) @@ -170,12 +172,12 @@ p2 + geom_parttree(data = iris_tree, aes(fill=Species), alpha = 0.1) ### Various front-end frameworks are also supported, e.g.: +# install.packages("parsnip") library(parsnip) -iris_tree_parsnip = - decision_tree() \%>\% - set_engine("rpart") \%>\% - set_mode("classification") \%>\% +iris_tree_parsnip = decision_tree() |> + set_engine("rpart") |> + set_mode("classification") |> fit(Species ~ Petal.Length + Petal.Width, data=iris) p + geom_parttree(data = iris_tree_parsnip, aes(fill=Species), alpha = 0.1) @@ -199,7 +201,8 @@ p3 ## Better to scale fill to the original data p3 + scale_fill_continuous(limits = range(iris$Petal.Length)) + } \seealso{ -\code{\link[=parttree]{parttree()}}, \code{\link[ggplot2:geom_tile]{ggplot2::geom_rect()}}. +\code{\link[=plot.parttree]{plot.parttree()}}, which provides an alternative plotting method using base R graphics. } diff --git a/vignettes/parttree-art.Rmd b/vignettes/parttree-art.Rmd index 5a8c842..b3e3ede 100644 --- a/vignettes/parttree-art.Rmd +++ b/vignettes/parttree-art.Rmd @@ -10,7 +10,11 @@ vignette: > ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, - comment = "#>" + comment = "#>", + out.width = "70%", + # fig.width = 8, + # dpi = 300, + asp = 0.625 ) ``` diff --git a/vignettes/parttree-intro.Rmd b/vignettes/parttree-intro.Rmd index 878ef6f..00f6906 100644 --- a/vignettes/parttree-intro.Rmd +++ b/vignettes/parttree-intro.Rmd @@ -11,7 +11,11 @@ vignette: > knitr::opts_chunk$set( collapse = TRUE, comment = "#>", - warning = FALSE + warning = FALSE, + out.width = "70%", + # fig.width = 8, + # dpi = 300, + asp = 0.625 ) ```