diff --git a/.Rbuildignore b/.Rbuildignore
index d2fede9..6fae4fc 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -7,3 +7,5 @@
^docs$
^pkgdown$
^SCRATCH$
+^cran-comments\.md$
+^CRAN-SUBMISSION$
diff --git a/.gitignore b/.gitignore
index 8c80211..5b4673d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@
docs
inst/doc
SCRATCH/
+**/*/.DS_Store
+.DS_Store
diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION
new file mode 100644
index 0000000..d963f3f
--- /dev/null
+++ b/CRAN-SUBMISSION
@@ -0,0 +1,3 @@
+Version: 0.1.0
+Date: 2025-01-15 02:46:58 UTC
+SHA: f5833ac6b32f3e95843b0dc9c44aff7e1b4c1dc3
diff --git a/DESCRIPTION b/DESCRIPTION
index 8da6e0d..9148d25 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,11 +1,12 @@
Package: parttree
-Title: Visualise simple decision tree partitions
-Version: 0.0.1.9006
+Title: Visualize Simple 2-D Decision Tree Partitions
+Version: 0.1.0
+Date: 2025-10-14
Authors@R: c(
person(given = "Grant",
family = "McDermott",
role = c("aut", "cre"),
- email = "grantmcd@uoregon.edu",
+ email = "gmcd@amazon.com",
comment = c(ORCID = "0000-0001-7883-8573")),
person(given = "Achim",
family = "Zeileis",
@@ -22,14 +23,20 @@ Authors@R: c(
role = "ctb",
email = "julia.silge@gmail.com",
comment = c(ORCID = "0000-0002-3671-836X")))
-Description: Simple functions for plotting 2D decision tree partition plots.
+Description: Visualize the partitions of simple decision trees, involving one or
+ two predictors, on the scale of the original data. Provides an intuitive
+ alternative to traditional tree diagrams, by visualizing how a decision tree
+ divides the predictor space in a simple 2D plot alongside the original data.
+ The 'parttree' package supports both classification and regression trees
+ from 'rpart' and 'partykit', as well as trees produced by popular frontend
+ systems like 'tidymodels' and 'mlr3'. Visualization methods are provided for
+ both base R graphics and 'ggplot2'.
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
LazyData: true
-URL: https://github.com/grantmcdermott/parttree,
- http://grantmcdermott.com/parttree
+URL: https://grantmcdermott.com/parttree/
BugReports: https://github.com/grantmcdermott/parttree/issues
Imports:
graphics,
diff --git a/NEWS.md b/NEWS.md
index 11f147d..c3600cd 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,12 +1,12 @@
-# parttree 0.0.1.9006
+# parttree 0.1.0
-To be released as 0.1.0
+Our first CRAN submission. 🎉🎉
#### Breaking changes
-* Move ggplot2 to Enhances, following the addition of native (base R)
-`plot.parttree` method. The `geom_parttree()` function now checks whether
-ggplot2 is available on the user's system before executing any code. (#18)
+* Move ggplot2 to Enhances, following the addition of a dedicated (base R)
+`plot.parttree` method. The `geom_parttree()` function is still available, but
+requires that ggplot2 is already been installed on the user's system. (#18)
* The `flipaxes` argument has been renamed to `flip`, e.g.
`parttree(..., flip = TRUE)`. (#18)
diff --git a/R/geom_parttree.R b/R/geom_parttree.R
index 1d48606..613dc0b 100644
--- a/R/geom_parttree.R
+++ b/R/geom_parttree.R
@@ -20,6 +20,7 @@
#' plot layers, note that the data input for `geom_parttree()` (i.e. decision
#' tree object) must assigned in the layer itself; not in the initialising
#' [ggplot2::ggplot()] call. See Examples.
+#' @returns A \code{\link[ggplot2]{ggplot}} layer.
#' @section Aesthetics:
#' \code{geom_parttree()} aims to "work-out-of-the-box" with minimal input from
#' the user's side, apart from specifying the data object. This includes taking
@@ -42,37 +43,39 @@
#'
#' library(parttree) # this package
#' library(rpart) # decision trees
-#'
-#' ### Simple decision tree (max of two predictor variables)
+#' \dontshow{data.table::setDTthreads(2)}
+#' #
+#' ## Simple decision tree (max of two predictor variables)
#'
#' iris_tree = rpart(Species ~ Petal.Length + Petal.Width, data=iris)
#'
-#' ## Plot with original iris data only
+#' # Plot with original iris data only
#' p = ggplot(data = iris, aes(x = Petal.Length, y = Petal.Width)) +
#' geom_point(aes(col = Species))
#'
-#' ## Add tree partitions to the plot (borders only)
+#' # Add tree partitions to the plot (borders only)
#' p + geom_parttree(data = iris_tree)
#'
-#' ## Better to use fill and highlight predictions
+#' # Better to use fill and highlight predictions
#' p + geom_parttree(data = iris_tree, aes(fill = Species), alpha=0.1)
#'
-#' ## To drop the black border lines (i.e. fill only)
+#' # To drop the black border lines (i.e. fill only)
#' p + geom_parttree(data = iris_tree, aes(fill = Species), col = NA, alpha = 0.1)
#'
-#'
-#' ### Example with plot orientation mismatch
+#' #
+#' ## Example with plot orientation mismatch
#'
#' p2 = ggplot(iris, aes(x=Petal.Width, y=Petal.Length)) +
#' geom_point(aes(col=Species))
#'
-#' ## Oops
+#' # Oops
#' p2 + geom_parttree(data = iris_tree, aes(fill=Species), alpha = 0.1)
#'
-#' ## Fix with 'flip = TRUE'
-#'
+#' # Fix with 'flip = TRUE'
+#' p2 + geom_parttree(data = iris_tree, aes(fill=Species), alpha = 0.1, flip = TRUE)
#'
-#' ### Various front-end frameworks are also supported, e.g.:
+#' #
+#' ## Various front-end frameworks are also supported, e.g.:
#'
#' # install.packages("parsnip")
#' library(parsnip)
@@ -84,10 +87,11 @@
#'
#' p + geom_parttree(data = iris_tree_parsnip, aes(fill=Species), alpha = 0.1)
#'
+#' #
+#' ## Trees with continuous independent variables are also supported.
#'
-#' ### Trees with continuous independent variables are also supported. But you
-#' ### may need to adjust (or switch off) the fill legend to match the original
-#' ### data, e.g.:
+#' # Note: you may need to adjust (or switch off) the fill legend to match the
+#' # original data, e.g.:
#'
#' iris_tree_cont = rpart(Petal.Length ~ Sepal.Length + Petal.Width, data=iris)
#' p3 = ggplot(data = iris, aes(x = Petal.Width, y = Sepal.Length)) +
@@ -98,10 +102,10 @@
#' geom_point(aes(col = Petal.Length)) +
#' theme_minimal()
#'
-#' ## Legend scales don't quite match here:
+#' # Legend scales don't quite match here:
#' p3
#'
-#' ## Better to scale fill to the original data
+#' # Better to scale fill to the original data
#' p3 + scale_fill_continuous(limits = range(iris$Petal.Length))
#'
#' @seealso [plot.parttree()], which provides an alternative plotting method using base R graphics.
diff --git a/R/parttree.R b/R/parttree.R
index 3a66551..2263110 100644
--- a/R/parttree.R
+++ b/R/parttree.R
@@ -15,6 +15,14 @@
#' data frame? The default behaviour is for the first split variable in the
#' tree to take the "y" slot, and any second split variable to take the "x"
#' slot. Setting to `TRUE` switches these around.
+#'
+#' _Note:_ This argument is primarily useful when it passed via
+#' [geom_parttree] to ensure correct axes orientation as part of a `ggplot2`
+#' visualization (see [geom_parttree] Examples). We do not expect users to
+#' call `parttree(..., flip = TRUE)` directly. Similarly, to switch axes
+#' orientation for the native (base graphics) [plot.parttree] method, we
+#' recommend calling `plot(..., flip = TRUE)` rather than flipping the
+#' underlying `parttree` object.
#' @seealso [plot.parttree], [geom_parttree], \code{\link[rpart]{rpart}},
#' \code{\link[partykit]{ctree}} [partykit::ctree].
#' @returns A data frame comprising seven columns: the leaf node, its path, a
@@ -26,7 +34,8 @@
#' @export
#' @examples
#' library("parttree")
-#'
+#' \dontshow{data.table::setDTthreads(2)}
+#' #
#' ## rpart trees
#'
#' library("rpart")
@@ -45,16 +54,17 @@
#' # customize further by passing extra options to (tiny)plot
#' plot(
#' rp_pt,
-#' border = NA, # no partition borders
-#' pch = 19, # filled points
-#' alpha = 0.6, # point transparency
-#' grid = TRUE, # background grid
-#' palette = "classic", # new colour palette
-#' xlab = "Topmost vertebra operated on", # custom x title
-#' ylab = "Patient age (months)", # custom y title
+#' border = NA, # no partition borders
+#' pch = 16, # filled points
+#' alpha = 0.6, # point transparency
+#' grid = TRUE, # background grid
+#' palette = "classic", # new colour palette
+#' xlab = "Topmost vertebra operated on", # custom x title
+#' ylab = "Patient age (months)", # custom y title
#' main = "Tree predictions: Kyphosis recurrence" # custom title
#' )
#'
+#' #
#' ## conditional inference trees from partyit
#'
#' library("partykit")
@@ -66,10 +76,12 @@
#' rp2 = as.party(rp)
#' parttree(rp2)
#'
+#' #
#' ## various front-end frameworks are also supported, e.g.
#'
#' # tidymodels
#'
+#' # install.packages("parsnip")
#' library(parsnip)
#'
#' decision_tree() |>
@@ -81,6 +93,7 @@
#'
#' # mlr3 (NB: use `keep_model = TRUE` for mlr3 learners)
#'
+#' # install.packages("mlr3")
#' library(mlr3)
#'
#' task_iris = TaskClassif$new("iris", iris, target = "Species")
@@ -157,15 +170,12 @@ parttree.rpart =
if (length(vars)==2) {
## special case we can assume is likely wrong, notwithstanding ability to still flip axes
if (vars[1]=="y" & vars[2]=="x") vars = rev(vars)
- }
- if (flip) {
- vars = rev(vars)
+ } else if (length(vars)==1) {
## Handle edge cases with only 1 level
- if (length(vars)==1) {
- missing_var = setdiff(attr(tree$terms, 'term.labels'), vars)
- vars = c(missing_var, vars)
- }
+ missing_var = setdiff(attr(tree$terms, 'term.labels'), vars)
+ vars = c(missing_var, vars)
}
+ if (flip) vars = rev(vars)
part_coords =
part_dt[
@@ -242,6 +252,7 @@ parttree.rpart =
response = y_var,
call = orig_call,
na.action = orig_na.action,
+ flip = flip,
raw_data = raw_data
)
@@ -472,6 +483,7 @@ parttree.constparty =
response = my,
call = NULL,
na.action = NULL,
+ flip = flip,
raw_data = substitute(tree$data) # Or, partykit::model_frame_rpart?
)
diff --git a/R/plot.R b/R/plot.R
index babb849..7c0a410 100644
--- a/R/plot.R
+++ b/R/plot.R
@@ -35,11 +35,20 @@ plot.parttree = function(
add = FALSE,
...
) {
+ dots = list(...)
object = x
- xvar = attr(object, "parttree")[["xvar"]]
- yvar = attr(object, "parttree")[["yvar"]]
- xrange = attr(object, "parttree")[["xrange"]]
- yrange = attr(object, "parttree")[["yrange"]]
+ flip_data = isTRUE(attr(object, "parttree")[["flip"]])
+ if (flip_data) {
+ xvar = attr(object, "parttree")[["yvar"]]
+ yvar = attr(object, "parttree")[["xvar"]]
+ xrange = attr(object, "parttree")[["yrange"]]
+ yrange = attr(object, "parttree")[["xrange"]]
+ } else {
+ xvar = attr(object, "parttree")[["xvar"]]
+ yvar = attr(object, "parttree")[["yvar"]]
+ xrange = attr(object, "parttree")[["xrange"]]
+ yrange = attr(object, "parttree")[["yrange"]]
+ }
response = attr(object, "parttree")[["response"]]
raw_data = attr(object, "parttree")[["raw_data"]]
orig_call = attr(object, "parttree")[["call"]]
@@ -109,10 +118,17 @@ plot.parttree = function(
# Grab the plot corners and adjust the partition limits
if (isTRUE(expand)) {
corners = par("usr")
- object$xmin[xmin_idxr] = corners[1]
- object$xmax[xmax_idxr] = corners[2]
- object$ymin[ymin_idxr] = corners[3]
- object$ymax[ymax_idxr] = corners[4]
+ if (isTRUE(dots[["flip"]])) {
+ object$xmin[xmin_idxr] = corners[3]
+ object$xmax[xmax_idxr] = corners[4]
+ object$ymin[ymin_idxr] = corners[1]
+ object$ymax[ymax_idxr] = corners[2]
+ } else {
+ object$xmin[xmin_idxr] = corners[1]
+ object$xmax[xmax_idxr] = corners[2]
+ object$ymin[ymin_idxr] = corners[3]
+ object$ymax[ymax_idxr] = corners[4]
+ }
}
diff --git a/README.Rmd b/README.Rmd
index 6160f87..9980bdb 100644
--- a/README.Rmd
+++ b/README.Rmd
@@ -16,6 +16,8 @@ knitr::opts_chunk$set(
# parttree
+[](https://CRAN.R-project.org/package=parttree)
+[](https://grantmcdermott.r-universe.dev)
[](https://github.com/grantmcdermott/parttree/actions/workflows/R-CMD-check.yaml)
[](https://grantmcdermott.com/parttree/index.html)
@@ -27,8 +29,14 @@ package provides visualization methods for both base R graphics (via
## Installation
-This package is not on CRAN yet, but can be installed from
-[r-universe](https://grantmcdermott.r-universe.dev/parttree):
+The stable version of **parttree** is available on CRAN.
+
+``` r
+install.packages("parttree")
+```
+
+Or, you can grab the latest development version from
+[R-universe](https://grantmcdermott.r-universe.dev/parttree).
``` r
install.packages("parttree", repos = "https://grantmcdermott.r-universe.dev")
@@ -60,15 +68,15 @@ Customize your plots by passing additional arguments:
```{r quickstart2}
plot(
- fit_pt,
- border = NA, # no partition borders
- pch = 19, # filled points
- alpha = 0.6, # point transparency
- grid = TRUE, # background grid
- palette = "classic", # new colour palette
- xlab = "Topmost vertebra operated on", # custom x title
- ylab = "Patient age (months)", # custom y title
- main = "Tree predictions: Kyphosis recurrence" # custom title
+ fit_pt,
+ border = NA, # no partition borders
+ pch = 19, # filled points
+ alpha = 0.6, # point transparency
+ grid = TRUE, # background grid
+ palette = "classic", # new colour palette
+ xlab = "Topmost vertebra operated on", # custom x title
+ ylab = "Patient age (months)", # custom y title
+ main = "Tree predictions: Kyphosis recurrence" # custom title
)
```
diff --git a/README.md b/README.md
index 3a261b3..eea7277 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,10 @@
+[](https://CRAN.R-project.org/package=parttree)
+[](https://grantmcdermott.r-universe.dev)
[](https://github.com/grantmcdermott/parttree/actions/workflows/R-CMD-check.yaml)
[](https://grantmcdermott.com/parttree/index.html)
@@ -16,8 +20,14 @@ package provides visualization methods for both base R graphics (via
## Installation
-This package is not on CRAN yet, but can be installed from
-[r-universe](https://grantmcdermott.r-universe.dev/parttree):
+The stable version of **parttree** is available on CRAN.
+
+``` r
+install.packages("parttree")
+```
+
+Or, you can grab the latest development version from
+[R-universe](https://grantmcdermott.r-universe.dev/parttree).
``` r
install.packages("parttree", repos = "https://grantmcdermott.r-universe.dev")
@@ -55,15 +65,15 @@ Customize your plots by passing additional arguments:
``` r
plot(
- fit_pt,
- border = NA, # no partition borders
- pch = 19, # filled points
- alpha = 0.6, # point transparency
- grid = TRUE, # background grid
- palette = "classic", # new colour palette
- xlab = "Topmost vertebra operated on", # custom x title
- ylab = "Patient age (months)", # custom y title
- main = "Tree predictions: Kyphosis recurrence" # custom title
+ fit_pt,
+ border = NA, # no partition borders
+ pch = 19, # filled points
+ alpha = 0.6, # point transparency
+ grid = TRUE, # background grid
+ palette = "classic", # new colour palette
+ xlab = "Topmost vertebra operated on", # custom x title
+ ylab = "Patient age (months)", # custom y title
+ main = "Tree predictions: Kyphosis recurrence" # custom title
)
```
diff --git a/cran-comments.md b/cran-comments.md
new file mode 100644
index 0000000..9dbf21e
--- /dev/null
+++ b/cran-comments.md
@@ -0,0 +1,9 @@
+## R CMD check results
+
+0 errors | 0 warnings | 1 note
+
+* This is a resubmission addressing the issues from my first submission on Jan
+ 11. Specifically, I've added a more detailed Description and fixed a missing
+ \value{} tag in one of my exported functions. Apologies for missing these the
+ first time around.
+* This is a new CRAN release.
diff --git a/inst/tinytest/_tinysnapshot/iris_classification_flip.svg b/inst/tinytest/_tinysnapshot/iris_classification_flip.svg
new file mode 100644
index 0000000..8698dc0
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/iris_classification_flip.svg
@@ -0,0 +1,230 @@
+
+
diff --git a/inst/tinytest/test_rpart.R b/inst/tinytest/test_rpart.R
index 8caee82..420cd6d 100644
--- a/inst/tinytest/test_rpart.R
+++ b/inst/tinytest/test_rpart.R
@@ -12,9 +12,15 @@ source('known_output/parttree_rpart_classification.R')
# rpart
rp = rpart::rpart(Species ~ Petal.Length + Petal.Width, data = iris)
rp_pt = parttree(rp)
+
# plot method
f = function() {plot(rp_pt)}
expect_snapshot_plot(f, label = "iris_classification")
+
+# ## uncomment once tinyplot 0.3.0 comes out
+# f = function() {plot(rp_pt, flip = TRUE)}
+# expect_snapshot_plot(f, label = "iris_classification_flip")
+
# now strip attributes and compare data frames
attr(rp_pt, "parttree") = NULL
class(rp_pt) = "data.frame"
@@ -40,6 +46,12 @@ if (require(partykit)) {
# Comparison data
source('known_output/parttree_rpart_classification_flip.R')
rp_pt_flip = parttree(rp, flip = TRUE)
+
+# plot method
+f = function() {plot(rp_pt_flip)}
+expect_snapshot_plot(f, label = "iris_classification_flip")
+
+# now strip attributes and compare data frames
attr(rp_pt_flip, "parttree") = NULL
class(rp_pt_flip) = "data.frame"
expect_equal(pt_cl_known_flip, rp_pt_flip)
diff --git a/man/figures/README-quickstart-1.png b/man/figures/README-quickstart-1.png
index bba8a5a..ef6a8a8 100644
Binary files a/man/figures/README-quickstart-1.png and b/man/figures/README-quickstart-1.png differ
diff --git a/man/figures/README-quickstart2-1.png b/man/figures/README-quickstart2-1.png
index e5c234e..711c798 100644
Binary files a/man/figures/README-quickstart2-1.png and b/man/figures/README-quickstart2-1.png differ
diff --git a/man/figures/README-quickstart_gg-1.png b/man/figures/README-quickstart_gg-1.png
index 0445a4f..6f623b1 100644
Binary files a/man/figures/README-quickstart_gg-1.png and b/man/figures/README-quickstart_gg-1.png differ
diff --git a/man/geom_parttree.Rd b/man/geom_parttree.Rd
index 8a99b1c..a1265b7 100644
--- a/man/geom_parttree.Rd
+++ b/man/geom_parttree.Rd
@@ -103,6 +103,9 @@ lists which parameters it can accept.
\link[ggplot2:draw_key]{key glyphs}, to change the display of the layer in the legend.
}}
}
+\value{
+A \code{\link[ggplot2]{ggplot}} layer.
+}
\description{
\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
@@ -140,37 +143,39 @@ library(ggplot2) # ggplot2 must be installed/loaded separately
library(parttree) # this package
library(rpart) # decision trees
-
-### Simple decision tree (max of two predictor variables)
+\dontshow{data.table::setDTthreads(2)}
+#
+## Simple decision tree (max of two predictor variables)
iris_tree = rpart(Species ~ Petal.Length + Petal.Width, data=iris)
-## Plot with original iris data only
+# Plot with original iris data only
p = ggplot(data = iris, aes(x = Petal.Length, y = Petal.Width)) +
geom_point(aes(col = Species))
-## Add tree partitions to the plot (borders only)
+# Add tree partitions to the plot (borders only)
p + geom_parttree(data = iris_tree)
-## Better to use fill and highlight predictions
+# Better to use fill and highlight predictions
p + geom_parttree(data = iris_tree, aes(fill = Species), alpha=0.1)
-## To drop the black border lines (i.e. fill only)
+# To drop the black border lines (i.e. fill only)
p + geom_parttree(data = iris_tree, aes(fill = Species), col = NA, alpha = 0.1)
-
-### Example with plot orientation mismatch
+#
+## Example with plot orientation mismatch
p2 = ggplot(iris, aes(x=Petal.Width, y=Petal.Length)) +
geom_point(aes(col=Species))
-## Oops
+# Oops
p2 + geom_parttree(data = iris_tree, aes(fill=Species), alpha = 0.1)
-## Fix with 'flip = TRUE'
-
+# Fix with 'flip = TRUE'
+p2 + geom_parttree(data = iris_tree, aes(fill=Species), alpha = 0.1, flip = TRUE)
-### Various front-end frameworks are also supported, e.g.:
+#
+## Various front-end frameworks are also supported, e.g.:
# install.packages("parsnip")
library(parsnip)
@@ -182,10 +187,11 @@ iris_tree_parsnip = decision_tree() |>
p + geom_parttree(data = iris_tree_parsnip, aes(fill=Species), alpha = 0.1)
+#
+## Trees with continuous independent variables are also supported.
-### Trees with continuous independent variables are also supported. But you
-### may need to adjust (or switch off) the fill legend to match the original
-### data, e.g.:
+# Note: you may need to adjust (or switch off) the fill legend to match the
+# original data, e.g.:
iris_tree_cont = rpart(Petal.Length ~ Sepal.Length + Petal.Width, data=iris)
p3 = ggplot(data = iris, aes(x = Petal.Width, y = Sepal.Length)) +
@@ -196,10 +202,10 @@ p3 = ggplot(data = iris, aes(x = Petal.Width, y = Sepal.Length)) +
geom_point(aes(col = Petal.Length)) +
theme_minimal()
-## Legend scales don't quite match here:
+# Legend scales don't quite match here:
p3
-## Better to scale fill to the original data
+# Better to scale fill to the original data
p3 + scale_fill_continuous(limits = range(iris$Petal.Length))
}
diff --git a/man/parttree.Rd b/man/parttree.Rd
index 4839975..26b8c5a 100644
--- a/man/parttree.Rd
+++ b/man/parttree.Rd
@@ -24,7 +24,15 @@ regular data frame (default behavior) unless the user specifies \code{TRUE}.}
\item{flip}{Logical. Should we flip the "x" and "y" variables in the return
data frame? The default behaviour is for the first split variable in the
tree to take the "y" slot, and any second split variable to take the "x"
-slot. Setting to \code{TRUE} switches these around.}
+slot. Setting to \code{TRUE} switches these around.
+
+\emph{Note:} This argument is primarily useful when it passed via
+\link{geom_parttree} to ensure correct axes orientation as part of a \code{ggplot2}
+visualization (see \link{geom_parttree} Examples). We do not expect users to
+call \code{parttree(..., flip = TRUE)} directly. Similarly, to switch axes
+orientation for the native (base graphics) \link{plot.parttree} method, we
+recommend calling \code{plot(..., flip = TRUE)} rather than flipping the
+underlying \code{parttree} object.}
}
\value{
A data frame comprising seven columns: the leaf node, its path, a
@@ -39,7 +47,8 @@ leaf or terminal node) that can easily be plotted in 2-D coordinate space.
}
\examples{
library("parttree")
-
+\dontshow{data.table::setDTthreads(2)}
+#
## rpart trees
library("rpart")
@@ -58,16 +67,17 @@ plot(rp_pt, border = NA)
# customize further by passing extra options to (tiny)plot
plot(
rp_pt,
- border = NA, # no partition borders
- pch = 19, # filled points
- alpha = 0.6, # point transparency
- grid = TRUE, # background grid
- palette = "classic", # new colour palette
- xlab = "Topmost vertebra operated on", # custom x title
- ylab = "Patient age (months)", # custom y title
+ border = NA, # no partition borders
+ pch = 16, # filled points
+ alpha = 0.6, # point transparency
+ grid = TRUE, # background grid
+ palette = "classic", # new colour palette
+ xlab = "Topmost vertebra operated on", # custom x title
+ ylab = "Patient age (months)", # custom y title
main = "Tree predictions: Kyphosis recurrence" # custom title
)
+#
## conditional inference trees from partyit
library("partykit")
@@ -79,10 +89,12 @@ plot(ct_pt, pch = 19, palette = "okabe", main = "ctree predictions: iris species
rp2 = as.party(rp)
parttree(rp2)
+#
## various front-end frameworks are also supported, e.g.
# tidymodels
+# install.packages("parsnip")
library(parsnip)
decision_tree() |>
@@ -94,6 +106,7 @@ decision_tree() |>
# mlr3 (NB: use `keep_model = TRUE` for mlr3 learners)
+# install.packages("mlr3")
library(mlr3)
task_iris = TaskClassif$new("iris", iris, target = "Species")
diff --git a/man/plot.parttree.Rd b/man/plot.parttree.Rd
index 29ab8d6..b1fa421 100644
--- a/man/plot.parttree.Rd
+++ b/man/plot.parttree.Rd
@@ -49,7 +49,8 @@ Provides a plot method for parttree objects.
}
\examples{
library("parttree")
-
+\dontshow{data.table::setDTthreads(2)}
+#
## rpart trees
library("rpart")
@@ -68,16 +69,17 @@ plot(rp_pt, border = NA)
# customize further by passing extra options to (tiny)plot
plot(
rp_pt,
- border = NA, # no partition borders
- pch = 19, # filled points
- alpha = 0.6, # point transparency
- grid = TRUE, # background grid
- palette = "classic", # new colour palette
- xlab = "Topmost vertebra operated on", # custom x title
- ylab = "Patient age (months)", # custom y title
+ border = NA, # no partition borders
+ pch = 16, # filled points
+ alpha = 0.6, # point transparency
+ grid = TRUE, # background grid
+ palette = "classic", # new colour palette
+ xlab = "Topmost vertebra operated on", # custom x title
+ ylab = "Patient age (months)", # custom y title
main = "Tree predictions: Kyphosis recurrence" # custom title
)
+#
## conditional inference trees from partyit
library("partykit")
@@ -89,10 +91,12 @@ plot(ct_pt, pch = 19, palette = "okabe", main = "ctree predictions: iris species
rp2 = as.party(rp)
parttree(rp2)
+#
## various front-end frameworks are also supported, e.g.
# tidymodels
+# install.packages("parsnip")
library(parsnip)
decision_tree() |>
@@ -104,6 +108,7 @@ decision_tree() |>
# mlr3 (NB: use `keep_model = TRUE` for mlr3 learners)
+# install.packages("mlr3")
library(mlr3)
task_iris = TaskClassif$new("iris", iris, target = "Species")
diff --git a/tests/tinytest.R b/tests/tinytest.R
index 5aa0983..e4e7455 100644
--- a/tests/tinytest.R
+++ b/tests/tinytest.R
@@ -1,5 +1,6 @@
if ( requireNamespace("tinytest", quietly=TRUE) ){
+ Sys.setenv("OMP_THREAD_LIMIT" = 2) # https://github.com/Rdatatable/data.table/issues/5658
tinytest::test_package("parttree")
}
diff --git a/vignettes/parttree-art.Rmd b/vignettes/parttree-art.Rmd
index 5a91fc8..512a829 100644
--- a/vignettes/parttree-art.Rmd
+++ b/vignettes/parttree-art.Rmd
@@ -28,7 +28,6 @@ This vignette will show you how to implement
the same basic ideas using **parttree** and a few friends. Here are the
packages that we'll be using.
-
```{r setup, message=FALSE}
library(parttree) # This package
library(rpart) # For decision trees
@@ -38,6 +37,11 @@ library(imager) # Another image library, with some additional features
op = par(mar = c(0,0,0,0)) # Remove plot margins
```
+```{r thread_control, echo=-1}
+data.table::setDTthreads(2)
+magick:::magick_threads(2)
+```
+
While the exact details will vary depending on the image at hand, the essential
recipe for this type of art abstraction is as follows:
diff --git a/vignettes/parttree-intro.Rmd b/vignettes/parttree-intro.Rmd
index fe7c88b..b887205 100644
--- a/vignettes/parttree-intro.Rmd
+++ b/vignettes/parttree-intro.Rmd
@@ -38,6 +38,10 @@ data("penguins", package = "palmerpenguins")
head(penguins)
```
+```{r thread_control, echo=-1}
+data.table::setDTthreads(2)
+```
+
Dataset in hand, let's say that we are interested in predicting penguin
_species_ as a function of 1) flipper length and 2) bill length. We could model
this as a simple decision tree:
@@ -84,7 +88,7 @@ ptree
Speaking of visualization, underneath the hood `plot.parttree` calls the
powerful
-[**tinyplot**](https://grantmcdermott.com/tinyplot)
+[**tinyplot**](https://grantmcdermott.com/tinyplot/)
package. All of the latter's various customization arguments can be passed on to
our `parttree` plot to make it look a bit nicer. For example:
@@ -109,10 +113,10 @@ tree_cont |>
## Supported model classes
-Alongside the [**rpart**](https://CRAN.R-project.org/web/package=rpart) model
+Alongside the [**rpart**](https://CRAN.R-project.org/package=rpart) model
objects that we have been working with thus far, **parttree** also supports
decision trees created by the
-[**partykit**](https://CRAN.R-project.org/web/package=partykit) package. Here we
+[**partykit**](https://CRAN.R-project.org/package=partykit) package. Here we
see how the latter's `ctree` (conditional inference tree) algorithm yields a
slightly more sophisticated partitioning that the former's default.
@@ -121,7 +125,7 @@ library(partykit)
ctree(species ~ flipper_length_mm + bill_length_mm, data = penguins) |>
parttree() |>
- plot(pch = 19, palette = "classic", alpha = 0.5)
+ plot(pch = 16, palette = "classic", alpha = 0.5)
```
**parttree** also supports a variety of "frontend" modes that call