-
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.
+
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
.
Examples
-
On this page
diff --git a/reference/index.html b/reference/index.html
index 4c96198..adf7c52 100644
--- a/reference/index.html
+++ b/reference/index.html
@@ -50,7 +50,7 @@ All functionsgeom_parttree()
- Visualise tree partitions with ggplot2
+ Visualize tree partitions with ggplot2
parttree()
diff --git a/search.json b/search.json
index 9193a9a..b74607a 100644
--- a/search.json
+++ b/search.json
@@ -1 +1 @@
-[{"path":"https://grantmcdermott.com/parttree/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2020 Grant McDermott Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"background","dir":"Articles","previous_headings":"","what":"Background","title":"Abstract art with parttree and friends","text":"One fun application tree-based methods abstracting art images. really striking examples, take look portfolio designer Dimitris Ladopoulos. vignette show implement basic ideas using parttree friends. packages ’ll using. exact details vary depending image hand, essential recipe type art abstraction follows: Convert image matrix (data frame), rows columns correspond, respectively, X Y coordinates individual pixels. words, cell matrix (data frame) represents colour values individual pixel. Split data primary (RGB) colour channels. now three matrices (data frames), cell represents red/green/blue colour channel value individual pixel. Run tree model three RGB datasets. case, trying predict relevant colour channel value function X Y coordinates. Use predicted values plot abstracted art piece! (Okay, step requires bit work, ’re see works practice…)","code":"library(parttree) # This package library(rpart) # For decision trees library(magick) # For reading and manipulating images library(imager) # Another image library, with some additional features op = par(mar = c(0,0,0,0)) # Remove plot margins"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"example-1-peales-portrait-of-rosalba","dir":"Articles","previous_headings":"","what":"Example 1: Peale’s “Portrait of Rosalba”","title":"Abstract art with parttree and friends","text":"first example, mimic one Dimitri Ladopoulos’s aforementioned portrait pieces. Specifically, abstract close-(eyes ) Rembrandt Peale’s portrait daughter, Rosalba. can download digital image original artwork Wikimedia. ’ll download high-res version show , feel free go lower resolution want reduce modeling plotting times.1 However, crop image around Rosalba’s eyes get close-reduce overall complexity exercise.2 cropped image hand, let’s walk 4-step recipe . Step 1 converting image data frame. Step 2 splitting image RGB colour channel. cc column , 1=Red, 2=Green, 3=Blue. Step 3 fitting decision tree (similar model) colour channel data frames. tuning parameters give model matter experimentation. ’m giving low complexity parameter (see variation final predictions) trimming tree maximum depth 30 nodes. next code chunk takes 15 seconds run laptop, much quicker downloaded lower-res image. Step 4 using model (colour) predictions construct abstracted art piece. bit glib earlier, since really involves sub-steps. First, let’s grab predictions trees. ’re going use predictions draw abstracted (downscaled) version image.3 Probably easiest way taking predictions overwriting “value” column original (pre-split) rosalba_df data frame. can coerce data frame back cimg object, comes bunch nice plotting methods. Now ’re ready draw abstracted art piece. ’s also parttree enter fray, since ’ll using highlight partitioned areas downscaled pixels. ’s can using base R plotting functions. can achieve effect ggplot2 prefer use .","code":"# Download the image rosalba = image_read(\"https://upload.wikimedia.org/wikipedia/commons/a/aa/Rembrandt_Peale_-_Portrait_of_Rosalba_Peale_-_Google_Art_Project.jpg\") # Crop around the eyes rosalba = image_crop(rosalba, \"850x400+890+1350\") # rosalba = image_crop(rosalba, \"750x350+890+1350\") # Convert to cimg (better for in-memory manipulation) rosalba = magick2cimg(rosalba) # Display rosalba #> Image. Width: 850 pix Height: 400 pix Depth: 1 Colour channels: 3 plot(rosalba, axes = FALSE) # Coerce to data frame rosalba_df = as.data.frame(rosalba) # Round color values to ease up work for decision tree rosalba_df$value = round(rosalba_df$value, 4) head(rosalba_df) #> x y cc value #> 1 1 1 1 0.3059 #> 2 2 1 1 0.3059 #> 3 3 1 1 0.2627 #> 4 4 1 1 0.2471 #> 5 5 1 1 0.3137 #> 6 6 1 1 0.2941 rosalba_ccs = split(rosalba_df, rosalba_df$cc) # We have a list of three DFs by colour channel. Uncomment if you want to see: # str(rosalba_css) ## Start creating regression tree for each color channel. We'll adjust some ## control parameters to give us the \"right\" amount of resolution in the final ## plots. trees = lapply( rosalba_ccs, # function(d) rpart(value ~ x + y, data=d, control=list(cp=0.00001, maxdepth=20)) function(d) rpart(value ~ x + y, data=d, control=list(cp=0.00002, maxdepth=20)) ) pred = lapply(trees, predict) # get predictions for each tree # The pred object is a list, so we convert it to a vector before overwriting the # value column of the original data frame rosalba_df$value = do.call(\"c\", pred) # Convert back into a cimg object, with the predictions providing pixel values pred_img = as.cimg(rosalba_df) #> Warning in as.cimg.data.frame(rosalba_df): Guessing image dimensions from #> maximum coordinate values # get a list of parttree data frames (one for each tree) pts = lapply(trees, parttree) ## first plot the downscaled image... plot(pred_img, axes = FALSE) ## ... then layer the partitions as a series of rectangles lapply( pts, function(pt) plot( pt, raw = FALSE, add = TRUE, expand = FALSE, fill_alpha = NULL, lwd = 0.1, border = \"grey15\" ) ) #> $`1` #> NULL #> #> $`2` #> NULL #> #> $`3` #> NULL library(ggplot2) ggplot() + annotation_raster(pred_img, ymin=-Inf, ymax=Inf, xmin=-Inf, xmax=Inf) + lapply(trees, function(d) geom_parttree(data = d, lwd = 0.05, col = \"grey15\")) + scale_x_continuous(limits=c(0, max(rosalba_df$x)), expand=c(0,0)) + scale_y_reverse(limits=c(max(rosalba_df$y), 0), expand=c(0,0)) + coord_fixed(ratio = Reduce(x = dim(rosalba)[2:1], f = \"/\") * 2) + theme_void()"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"example-2-parttree-logo","dir":"Articles","previous_headings":"","what":"Example 2: parttree logo","title":"Abstract art with parttree and friends","text":"Now ’ve walked detailed example, let’s quickly go one . ’re get meta: Visualizing decision tree partitions actual tree image. also happens basis parttree logo, seems nice way bookend vignette. main image conversion, modeling, prediction steps. follow recipe saw previous portrait example, won’t repeat explanations. point may tempted plot figure plot(bonzai_pred_img), definitely work. However, ’m going show one additional tweak make partition rectangles look bit nicer: Use mean color channel values instead black. ’s function grabbing information cimg object converted data frame.4 penultimate step generate parttree objects colour channel-based trees. now can plot everything together. , equivalent result prefer ggplot2.","code":"bonzai = load.image(\"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Japanese_Zelkova_bonsai_16%2C_30_April_2012.JPG/480px-Japanese_Zelkova_bonsai_16%2C_30_April_2012.JPG\") plot(bonzai, axes = FALSE) # Coerce to data frame bonzai_df = as.data.frame(bonzai) # Round color values to ease up work for decision trees bonzai_df$value = round(bonzai_df$value, 2) # Split into colour channels bonzai_ccs = split(bonzai_df, bonzai_df$cc) # Fit decision trees on each colour channel DF. Note that I'm deliberating # truncating the max tree depth to reduce the number of partitions. bonzai_trees = lapply( bonzai_ccs, function(d) rpart(value ~ x + y, data=d, control=list(cp=0.00001, maxdepth=10)) ) # Overwrite value column with predictions vector bonzai_df$value = do.call(\"c\", lapply(bonzai_trees, predict)) # Convert back into a cimg object, with the predictions providing pixel values bonzai_pred_img = as.cimg(bonzai_df) #> Warning in as.cimg.data.frame(bonzai_df): Guessing image dimensions from #> maximum coordinate values mean_cols = function(dat) { mcols = tapply(dat$value, dat$cc, FUN = \"mean\") col1 = rgb(mcols[1], mcols[2], mcols[3]) hicol = function(x) mean(x) + 0.4*sd(subset(dat, cc==1)$value) col2 = rgb(hicol(subset(dat, cc==1)$value), hicol(subset(dat, cc==2)$value), hicol(subset(dat, cc==3)$value)) locol = function(x) mean(x) - 0.4*sd(subset(dat, cc==1)$value) col3 = rgb(locol(subset(dat, cc==1)$value), locol(subset(dat, cc==2)$value), locol(subset(dat, cc==3)$value)) return(c(col1, col2, col3)) } bonzai_mean_cols = mean_cols(bonzai_df) bonzai_pts = lapply(bonzai_trees, parttree) plot(bonzai_pred_img, axes = FALSE) Map( function(pt, cols) { plot( pt, raw = FALSE, add = TRUE, expand = FALSE, fill_alpha = 0, lwd = 0.2, border = cols ) }, pt = bonzai_pts, cols = bonzai_mean_cols ) #> $`1` #> NULL #> #> $`2` #> NULL #> #> $`3` #> NULL # library(ggplot2) ggplot() + annotation_raster(bonzai_pred_img, ymin=-Inf, ymax=Inf, xmin=-Inf, xmax=Inf) + Map(function(d, cols) geom_parttree(data = d, lwd = 0.1, col = cols), d = bonzai_trees, cols = bonzai_mean_cols) + scale_x_continuous(limits=c(0, max(bonzai_df$x)), expand=c(0,0)) + scale_y_reverse(limits=c(max(bonzai_df$y), 0), expand=c(0,0)) + coord_fixed() + theme_void()"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"postscript","dir":"Articles","previous_headings":"","what":"Postscript","title":"Abstract art with parttree and friends","text":"individual trees colour channel make nice stained glass prints…","code":"lapply( seq_along(bonzai_pts), function(i) { plot( bonzai_pts[[i]], raw = FALSE, expand = FALSE, axes = FALSE, legend = FALSE, main = paste0(c(\"R\", \"G\", \"B\")[i]), ## Aside: We're reversing the y-scale since higher values actually ## correspond to points lower on the image, visually. ylim = rev(attr(bonzai_pts[[i]], \"parttree\")[[\"yrange\"]]) ) } ) #> [[1]] #> NULL #> #> [[2]] #> NULL #> #> [[3]] #> NULL # reset the plot margins par(op)"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"motivating-example-classifying-penguin-species","dir":"Articles","previous_headings":"","what":"Motivating example: Classifying penguin species","title":"Introduction to parttree","text":"Start loading parttree package alongside rpart, comes bundled base R installation. basic examples follow, ’ll use well-known Palmer Penguins dataset demonstrate functionality. can load dataset via parent package (), import directly CSV . Dataset hand, let’s say interested predicting penguin species function 1) flipper length 2) bill length. model simple decision tree: Like tree-based frameworks, rpart comes default plot method visualizing resulting node splits. okay, don’t feel provides much intuition model’s prediction scale actual data. words, ’d prefer see : tree partitioned original penguin data? parttree enters fray. package named primary workhorse function parttree(), extracts information needed produce nice plot tree partitions alongside original data. Et voila! Now can clearly see model divided Cartesian space data. Gentoo penguins typically longer flippers Chinstrap Adelie penguins, latter shortest bills. perspective end-user, ptree parttree object interesting . simply data frame contains basic information needed plot (partition coordinates, etc.). can think helpful intermediate object way visualization interest. Speaking visualization, underneath hood plot.parttree calls powerful tinyplot package. latter’s various customization arguments can passed parttree plot make look bit nicer. example:","code":"library(parttree) # This package library(rpart) # For fitting decisions trees # install.packages(\"palmerpenguins\") data(\"penguins\", package = \"palmerpenguins\") head(penguins) #> # A tibble: 6 × 8 #> species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g #> #> 1 Adelie Torgersen 39.1 18.7 181 3750 #> 2 Adelie Torgersen 39.5 17.4 186 3800 #> 3 Adelie Torgersen 40.3 18 195 3250 #> 4 Adelie Torgersen NA NA NA NA #> 5 Adelie Torgersen 36.7 19.3 193 3450 #> 6 Adelie Torgersen 39.3 20.6 190 3650 #> # ℹ 2 more variables: sex , year tree = rpart(species ~ flipper_length_mm + bill_length_mm, data = penguins) tree #> n=342 (2 observations deleted due to missingness) #> #> node), split, n, loss, yval, (yprob) #> * denotes terminal node #> #> 1) root 342 191 Adelie (0.441520468 0.198830409 0.359649123) #> 2) flipper_length_mm< 206.5 213 64 Adelie (0.699530516 0.295774648 0.004694836) #> 4) bill_length_mm< 43.35 150 5 Adelie (0.966666667 0.033333333 0.000000000) * #> 5) bill_length_mm>=43.35 63 5 Chinstrap (0.063492063 0.920634921 0.015873016) * #> 3) flipper_length_mm>=206.5 129 7 Gentoo (0.015503876 0.038759690 0.945736434) * plot(tree, compress = TRUE) text(tree, use.n = TRUE) ptree = parttree(tree) plot(ptree) # See also `attr(ptree, \"parttree\")` ptree #> node species path xmin #> 1 3 Gentoo flipper_length_mm >= 206.5 206.5 #> 2 4 Adelie flipper_length_mm < 206.5 --> bill_length_mm < 43.35 -Inf #> 3 5 Chinstrap flipper_length_mm < 206.5 --> bill_length_mm >= 43.35 -Inf #> xmax ymin ymax #> 1 Inf -Inf Inf #> 2 206.5 -Inf 43.35 #> 3 206.5 43.35 Inf plot(ptree, pch = 16, palette = \"classic\", alpha = 0.75, grid = TRUE)"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"continuous-predictions","dir":"Articles","previous_headings":"Motivating example: Classifying penguin species","what":"Continuous predictions","title":"Introduction to parttree","text":"addition discrete classification problems, parttree also supports regression trees continuous independent variables.","code":"tree_cont = rpart(body_mass_g ~ flipper_length_mm + bill_length_mm, data = penguins) tree_cont |> parttree() |> plot(pch = 16, palette = \"viridis\")"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"supported-model-classes","dir":"Articles","previous_headings":"","what":"Supported model classes","title":"Introduction to parttree","text":"Alongside rpart model objects working thus far, parttree also supports decision trees created partykit package. see latter’s ctree (conditional inference tree) algorithm yields slightly sophisticated partitioning former’s default. parttree also supports variety “frontend” modes call rpart::rpart() underlying engine. includes packages mlr3 tidymodels (parsnip workflows) ecosystems. quick demonstration using parsnip, ’ll also pull different dataset just change things little.","code":"library(partykit) #> Loading required package: grid #> Loading required package: libcoin #> Loading required package: mvtnorm ctree(species ~ flipper_length_mm + bill_length_mm, data = penguins) |> parttree() |> plot(pch = 19, palette = \"classic\", alpha = 0.5) set.seed(123) ## For consistent jitter library(parsnip) library(titanic) ## Just for a different data set titanic_train$Survived = as.factor(titanic_train$Survived) ## Build our tree using parsnip (but with rpart as the model engine) ti_tree = decision_tree() |> set_engine(\"rpart\") |> set_mode(\"classification\") |> fit(Survived ~ Pclass + Age, data = titanic_train) ## Now pass to parttree and plot ti_tree |> parttree() |> plot(pch = 16, jitter = TRUE, palette = \"dark\", alpha = 0.7)"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"ggplot2","dir":"Articles","previous_headings":"","what":"ggplot2","title":"Introduction to parttree","text":"default plot.parttree method produces base graphics plot. also support ggplot2 via dedicated geom_parttree() function. demonstrate initial classification tree earlier. Compared “native” plot.parttree method, note ggplot2 workflow requires tweaks: need need plot original dataset separate layer (.e., geom_point()). geom_parttree() accepts tree object , result parttree().1 Continuous regression trees can also drawn geom_parttree. However, recommend adjusting plot fill aesthetic since model likely partition data intervals don’t match exactly raw data. easiest way setting colour fill aesthetic together part scale_colour_* call.","code":"library(ggplot2) theme_set(theme_linedraw()) ## re-using the tree model object from above... ggplot(data = penguins, aes(x = flipper_length_mm, y = bill_length_mm)) + geom_point(aes(col = species)) + geom_parttree(data = tree, aes(fill=species), alpha = 0.1) ## re-using the tree_cont model object from above... ggplot(data = penguins, aes(x = flipper_length_mm, y = bill_length_mm)) + geom_parttree(data = tree_cont, aes(fill=body_mass_g), alpha = 0.3) + geom_point(aes(col = body_mass_g)) + scale_colour_viridis_c(aesthetics = c('colour', 'fill')) # NB: Set colour + fill together"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"gotcha-ggplot-orientation","dir":"Articles","previous_headings":"ggplot2","what":"Gotcha: (gg)plot orientation","title":"Introduction to parttree","text":"already said, geom_parttree() calls companion parttree() function internally, coerces rpart tree object data frame easily understood ggplot2. example, consider initial “ptree” object earlier. , resulting data frame designed amenable ggplot2 geom layer, columns like xmin, xmax, etc. specifying aesthetics ggplot2 recognizes. (Fun fact: geom_parttree() really just thin wrapper around geom_rect().) goal parttree abstract away kinds details user, can just specify geom_parttree()—valid tree object data input—done . However, generally works well, can sometimes lead unexpected behaviour terms plot orientation. ’s ’s hard guess ahead time user specify x y variables (.e. axes) ggplot2 layers.2 see mean, let’s redo penguin plot earlier, time switch axes main ggplot() call. case , kind orientation mismatch normally (hopefully) pretty easy recognize. fix, can use flip = TRUE argument flip orientation geom_parttree layer.","code":"# ptree = parttree(tree) ptree #> node species path xmin #> 1 3 Gentoo flipper_length_mm >= 206.5 206.5 #> 2 4 Adelie flipper_length_mm < 206.5 --> bill_length_mm < 43.35 -Inf #> 3 5 Chinstrap flipper_length_mm < 206.5 --> bill_length_mm >= 43.35 -Inf #> xmax ymin ymax #> 1 Inf -Inf Inf #> 2 206.5 -Inf 43.35 #> 3 206.5 43.35 Inf ## First, redo our first plot but this time switch the x and y variables p3 = ggplot( data = penguins, aes(x = bill_length_mm, y = flipper_length_mm) ## Switched! ) + geom_point(aes(col = species)) ## Add on our tree (and some preemptive titling..) p3 + geom_parttree(data = tree, aes(fill = species), alpha = 0.1) + labs( title = \"Oops!\", subtitle = \"Looks like a mismatch between our x and y axes...\" ) p3 + geom_parttree( data = tree, aes(fill = species), alpha = 0.1, flip = TRUE ## Flip the orientation ) + labs(title = \"That's better\")"},{"path":"https://grantmcdermott.com/parttree/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Grant McDermott. Author, maintainer. Achim Zeileis. Contributor. Brian Heseung Kim. Contributor. Julia Silge. Contributor.","code":""},{"path":"https://grantmcdermott.com/parttree/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"McDermott G (2025). parttree: Visualise simple decision tree partitions. R package version 0.0.1.9005, http://grantmcdermott.com/parttree, https://github.com/grantmcdermott/parttree.","code":"@Manual{, title = {parttree: Visualise simple decision tree partitions}, author = {Grant McDermott}, year = {2025}, note = {R package version 0.0.1.9005, http://grantmcdermott.com/parttree}, url = {https://github.com/grantmcdermott/parttree}, }"},{"path":"https://grantmcdermott.com/parttree/index.html","id":"parttree-","dir":"","previous_headings":"","what":"Visualise simple decision tree partitions","title":"Visualise simple decision tree partitions","text":"Visualize simple 2-D decision tree partitions R. parttree package provides visualization methods base R graphics (via tinyplot) ggplot2.","code":""},{"path":"https://grantmcdermott.com/parttree/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Visualise simple decision tree partitions","text":"package CRAN yet, can installed r-universe:","code":"install.packages(\"parttree\", repos = \"https://grantmcdermott.r-universe.dev\")"},{"path":"https://grantmcdermott.com/parttree/index.html","id":"quickstart","dir":"","previous_headings":"","what":"Quickstart","title":"Visualise simple decision tree partitions","text":"parttree homepage includes introductory vignette detailed documentation. ’s quickstart example using “kyphosis” dataset comes bundled rpart package. case, interested predicting kyphosis recovery spinal surgery, function 1) number topmost vertebra operated, 2) patient age. key function parttree(), comes plotting method. Customize plots passing additional arguments:","code":"library(rpart) # For the dataset and fitting decisions trees library(parttree) # This package fit = rpart(Kyphosis ~ Start + Age, data = kyphosis) # Grab the partitions and plot fit_pt = parttree(fit) plot(fit_pt) 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 )"},{"path":"https://grantmcdermott.com/parttree/index.html","id":"ggplot2","dir":"","previous_headings":"Quickstart","what":"ggplot2","title":"Visualise simple decision tree partitions","text":"ggplot2 users, offer equivalent workflow via geom_partree() visualization layer.","code":"library(ggplot2) ## Should be loaded separately ggplot(kyphosis, aes(x = Start, y = Age)) + geom_parttree(data = fit, alpha = 0.1, aes(fill = Kyphosis)) + # <-- key layer geom_point(aes(col = Kyphosis)) + labs( x = \"No. of topmost vertebra operated on\", y = \"Patient age (months)\", caption = \"Note: Points denote observations. Shading denotes model predictions.\" ) + theme_minimal()"},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":null,"dir":"Reference","previous_headings":"","what":"Visualise tree partitions with ggplot2 — geom_parttree","title":"Visualise tree partitions with ggplot2 — geom_parttree","text":"geom_parttree() simple extension ggplot2::geom_rect()first calls parttree() convert inputted tree object amenable data frame. Please note ggplot2 hard dependency parttree thus installed separately user's system.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Visualise tree partitions with ggplot2 — geom_parttree","text":"","code":"geom_parttree( mapping = NULL, data = NULL, stat = \"identity\", position = \"identity\", linejoin = \"mitre\", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, flip = FALSE, ... )"},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Visualise tree partitions with ggplot2 — geom_parttree","text":"mapping Set aesthetic mappings created aes(). specified inherit.aes = TRUE (default), combined default mapping top level plot. must supply mapping plot mapping. data rpart::rpart.object object compatible type (e.g. decision tree constructed via partykit, tidymodels, mlr3 front-ends). stat statistical transformation use data layer. using geom_*() function construct layer, stat argument can used override default coupling geoms stats. stat argument accepts following: Stat ggproto subclass, example StatCount. string naming stat. give stat string, strip function name stat_ prefix. example, use stat_count(), give stat \"count\". information ways specify stat, see layer stat documentation. position position adjustment use data layer. can used various ways, including prevent overplotting improving display. position argument accepts following: result calling position function, position_jitter(). method allows passing extra arguments position. string naming position adjustment. give position string, strip function name position_ prefix. example, use position_jitter(), give position \"jitter\". information ways specify position, see layer position documentation. linejoin Line join style (round, mitre, bevel). na.rm FALSE, default, missing values removed warning. TRUE, missing values silently removed. show.legend logical. layer included legends? NA, default, includes aesthetics mapped. FALSE never includes, TRUE always includes. can also named logical vector finely select aesthetics display. inherit.aes FALSE, overrides default aesthetics, rather combining . useful helper functions define data aesthetics inherit behaviour default plot specification, e.g. borders(). flip Logical. default, \"x\" \"y\" axes variables plotting determined first split tree. can cause plot orientation mismatches depending users specify layers plot. Setting TRUE flip \"x\" \"y\" variables geom_parttree layer. ... arguments passed layer()'s params argument. arguments broadly fall one 4 categories . Notably, arguments position argument, aesthetics required can passed .... Unknown arguments part 4 categories ignored. Static aesthetics mapped scale, fixed value apply layer whole. example, colour = \"red\" linewidth = 3. geom's documentation Aesthetics section lists available options. 'required' aesthetics passed params. Please note passing unmapped aesthetics vectors technically possible, order required length guaranteed parallel input data. constructing layer using stat_*() function, ... argument can used pass parameters geom part layer. example stat_density(geom = \"area\", outline.type = \"\"). geom's documentation lists parameters can accept. Inversely, constructing layer using geom_*() function, ... argument can used pass parameters stat part layer. example geom_area(stat = \"density\", adjust = 0.5). stat's documentation lists parameters can accept. key_glyph argument layer() may also passed .... can one functions described key glyphs, change display layer legend.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Visualise tree partitions with ggplot2 — geom_parttree","text":"way ggplot2 validates inputs assembles plot layers, note data input geom_parttree() (.e. decision tree object) must assigned layer ; initialising ggplot2::ggplot() call. See Examples.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"aesthetics","dir":"Reference","previous_headings":"","what":"Aesthetics","title":"Visualise tree partitions with ggplot2 — geom_parttree","text":"geom_parttree() aims \"work----box\" minimal input user's side, apart specifying data object. includes taking care data transformation way , generally, produces optimal corner coordinates partition (.e. xmin, xmax, ymin, ymax). However, also understands following aesthetics users may choose specify manually: fill (particularly encouraged, since provide visual cue regarding prediction partition region) colour alpha linetype size","code":""},{"path":[]},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Visualise tree partitions with ggplot2 — geom_parttree","text":"","code":"library(parttree) # this package library(rpart) # decision trees library(ggplot2) # ggplot2 must be loaded separately ### Simple decision tree (max of two predictor variables) iris_tree = rpart(Species ~ Petal.Length + Petal.Width, data=iris) ## 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) p + geom_parttree(data = iris_tree) ## 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) p + geom_parttree(data = iris_tree, aes(fill = Species), col = NA, alpha = 0.1) ### Example with plot orientation mismatch p2 = ggplot(iris, aes(x=Petal.Width, y=Petal.Length)) + geom_point(aes(col=Species)) ## Oops p2 + geom_parttree(data = iris_tree, aes(fill=Species), alpha = 0.1) ## Fix with 'flip = TRUE' ### Various front-end frameworks are also supported, e.g.: library(parsnip) 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) ### 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.: iris_tree_cont = rpart(Petal.Length ~ Sepal.Length + Petal.Width, data=iris) p3 = ggplot(data = iris, aes(x = Petal.Width, y = Sepal.Length)) + geom_parttree( data = iris_tree_cont, aes(fill = Petal.Length), alpha=0.5 ) + geom_point(aes(col = Petal.Length)) + theme_minimal() ## Legend scales don't quite match here: p3 ## Better to scale fill to the original data p3 + scale_fill_continuous(limits = range(iris$Petal.Length))"},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert a decision tree into a data frame of partition coordinates — parttree","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"Extracts terminal leaf nodes decision tree contains two numeric predictor variables. leaf nodes converted data frame, row represents partition (leaf terminal node) can easily plotted 2-D coordinate space.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"","code":"parttree(tree, keep_as_dt = FALSE, flip = FALSE)"},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"tree rpart.object alike. includes compatible classes mlr3 tidymodels frontends, constparty class inheriting party. keep_as_dt Logical. function relies data.table internal data manipulation. coerce final return object regular data frame (default behavior) unless user specifies TRUE. flip Logical. flip \"x\" \"y\" variables return data frame? default behaviour first split variable tree take \"y\" slot, second split variable take \"x\" slot. Setting TRUE switches around.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"data frame comprising seven columns: leaf node, path, set rectangle limits (.e., xmin, xmax, ymin, ymax), final column corresponding predicted value leaf.","code":""},{"path":[]},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"","code":"library(\"parttree\") ## rpart trees library(\"rpart\") rp = rpart(Kyphosis ~ Start + Age, data = kyphosis) # A parttree object is just a data frame with additional attributes (rp_pt = parttree(rp)) #> node Kyphosis path xmin #> 1 3 present Start < 8.5 -Inf #> 2 4 absent Start >= 8.5 --> Start >= 14.5 14.5 #> 3 10 absent Start >= 8.5 --> Start < 14.5 --> Age < 55 8.5 #> 4 22 absent Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 5 23 present Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age < 111 8.5 #> xmax ymin ymax #> 1 8.5 -Inf Inf #> 2 Inf -Inf Inf #> 3 14.5 -Inf 55 #> 4 14.5 111 Inf #> 5 14.5 55 111 attr(rp_pt, \"parttree\") #> $xvar #> [1] \"Start\" #> #> $yvar #> [1] \"Age\" #> #> $xrange #> [1] 1 18 #> #> $yrange #> [1] 1 206 #> #> $response #> [1] \"Kyphosis\" #> #> $call #> rpart(formula = Kyphosis ~ Start + Age, data = kyphosis) #> #> $na.action #> NULL #> #> $raw_data #> NULL #> # simple plot plot(rp_pt) # removing the (recursive) partition borders helps to emphasise overall fit 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 main = \"Tree predictions: Kyphosis recurrence\" # custom title ) ## conditional inference trees from partyit library(\"partykit\") #> Loading required package: grid #> Loading required package: libcoin #> Loading required package: mvtnorm ct = ctree(Species ~ Petal.Length + Petal.Width, data = iris) ct_pt = parttree(ct) plot(ct_pt, pch = 19, palette = \"okabe\", main = \"ctree predictions: iris species\") #> Error in eval(raw_data): object 'ct' not found ## rpart via partykit rp2 = as.party(rp) parttree(rp2) #> node Kyphosis path xmin #> 3 3 absent Start < 8.5 --> Start < 14.5 14.5 #> 5 5 absent Start < 8.5 --> Start >= 14.5 --> Age < 55 8.5 #> 7 7 absent Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age < 111 8.5 #> 8 8 present Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 9 9 present Start >= 8.5 -Inf #> xmax ymin ymax #> 3 Inf -Inf Inf #> 5 14.5 -Inf 55 #> 7 14.5 111 Inf #> 8 14.5 55 111 #> 9 8.5 -Inf Inf ## various front-end frameworks are also supported, e.g. # tidymodels library(parsnip) decision_tree() |> set_engine(\"rpart\") |> set_mode(\"classification\") |> fit(Species ~ Petal.Length + Petal.Width, data=iris) |> parttree() |> plot(main = \"This time brought to you via parsnip...\") # mlr3 (NB: use `keep_model = TRUE` for mlr3 learners) library(mlr3) task_iris = TaskClassif$new(\"iris\", iris, target = \"Species\") task_iris$formula(rhs = \"Petal.Length + Petal.Width\") #> Species ~ `Petal.Length + Petal.Width` #> NULL fit_iris = lrn(\"classif.rpart\", keep_model = TRUE) # NB! fit_iris$train(task_iris) plot(parttree(fit_iris), main = \"... and now mlr3\")"},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot decision tree partitions — plot.parttree","title":"Plot decision tree partitions — plot.parttree","text":"Provides plot method parttree objects.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot decision tree partitions — plot.parttree","text":"","code":"# S3 method for class 'parttree' plot( x, raw = TRUE, border = \"black\", fill_alpha = 0.3, expand = TRUE, jitter = FALSE, add = FALSE, ... )"},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot decision tree partitions — plot.parttree","text":"x parttree data frame. raw Logical. raw (original) data points plotted ? Default TRUE. border Colour partition borders (edges). Default \"black\". remove borders altogether, specify NA. fill_alpha Numeric range [0,1]. Alpha transparency filled partition rectangles. Default 0.3. expand Logical. partition limits expanded meet edge plot axes? Default TRUE. FALSE, partition limits extend range raw data. jitter Logical. raw points jittered? Default FALSE. evaluated raw = TRUE. add Logical. Add existing plot? Default FALSE. ... Additional arguments passed tinyplot.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot decision tree partitions — plot.parttree","text":"return value, called side effect producing plot. return value; called side effect producing plot.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot decision tree partitions — plot.parttree","text":"","code":"library(\"parttree\") ## rpart trees library(\"rpart\") rp = rpart(Kyphosis ~ Start + Age, data = kyphosis) # A parttree object is just a data frame with additional attributes (rp_pt = parttree(rp)) #> node Kyphosis path xmin #> 1 3 present Start < 8.5 -Inf #> 2 4 absent Start >= 8.5 --> Start >= 14.5 14.5 #> 3 10 absent Start >= 8.5 --> Start < 14.5 --> Age < 55 8.5 #> 4 22 absent Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 5 23 present Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age < 111 8.5 #> xmax ymin ymax #> 1 8.5 -Inf Inf #> 2 Inf -Inf Inf #> 3 14.5 -Inf 55 #> 4 14.5 111 Inf #> 5 14.5 55 111 attr(rp_pt, \"parttree\") #> $xvar #> [1] \"Start\" #> #> $yvar #> [1] \"Age\" #> #> $xrange #> [1] 1 18 #> #> $yrange #> [1] 1 206 #> #> $response #> [1] \"Kyphosis\" #> #> $call #> rpart(formula = Kyphosis ~ Start + Age, data = kyphosis) #> #> $na.action #> NULL #> #> $raw_data #> NULL #> # simple plot plot(rp_pt) # removing the (recursive) partition borders helps to emphasise overall fit 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 main = \"Tree predictions: Kyphosis recurrence\" # custom title ) ## conditional inference trees from partyit library(\"partykit\") ct = ctree(Species ~ Petal.Length + Petal.Width, data = iris) ct_pt = parttree(ct) plot(ct_pt, pch = 19, palette = \"okabe\", main = \"ctree predictions: iris species\") #> Error in eval(raw_data): object 'ct' not found ## rpart via partykit rp2 = as.party(rp) parttree(rp2) #> node Kyphosis path xmin #> 3 3 absent Start < 8.5 --> Start < 14.5 14.5 #> 5 5 absent Start < 8.5 --> Start >= 14.5 --> Age < 55 8.5 #> 7 7 absent Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age < 111 8.5 #> 8 8 present Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 9 9 present Start >= 8.5 -Inf #> xmax ymin ymax #> 3 Inf -Inf Inf #> 5 14.5 -Inf 55 #> 7 14.5 111 Inf #> 8 14.5 55 111 #> 9 8.5 -Inf Inf ## various front-end frameworks are also supported, e.g. # tidymodels library(parsnip) decision_tree() |> set_engine(\"rpart\") |> set_mode(\"classification\") |> fit(Species ~ Petal.Length + Petal.Width, data=iris) |> parttree() |> plot(main = \"This time brought to you via parsnip...\") # mlr3 (NB: use `keep_model = TRUE` for mlr3 learners) library(mlr3) task_iris = TaskClassif$new(\"iris\", iris, target = \"Species\") task_iris$formula(rhs = \"Petal.Length + Petal.Width\") #> Species ~ `Petal.Length + Petal.Width` #> NULL fit_iris = lrn(\"classif.rpart\", keep_model = TRUE) # NB! fit_iris$train(task_iris) plot(parttree(fit_iris), main = \"... and now mlr3\")"},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"parttree-0019005","dir":"Changelog","previous_headings":"","what":"parttree 0.0.1.9005","title":"parttree 0.0.1.9005","text":"released 0.1.0","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"breaking-changes-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Breaking changes","title":"parttree 0.0.1.9005","text":"Move ggplot2 Suggests, following addition native (base R) plot.parttree method. geom_parttree() function now checks whether ggplot2 available user’s system executing code. (#18) flipaxes argument renamed flip, e.g. parttree(..., flip = TRUE). (#18)","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"improvements-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Improvements","title":"parttree 0.0.1.9005","text":"Parttree objects now class dedicated plot.parttree method, powered tinyplot. (#18) Major speed-extracting parttree nodes coordinates complicated trees. (#15) Add method tidymodels workflows objects fitted \"rpart\" engine. (#7 @juliasilge).","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"bug-fixes-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Bug fixes","title":"parttree 0.0.1.9005","text":"Support negative values. (#6 @pjgeens) Better handling single-level factors flip(axes). (#5)","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"internals-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Internals","title":"parttree 0.0.1.9005","text":"Several dependency adjustments, e.g. tinyplot Imports ggplot2 Suggests. (#18) Added SVG snapshots image-based tests. (#18) Bump ggplot2 version dependency match deprecated functions 3.4.0. Switched “main” primary GitHub branch development. Added two dedicated vignettes.","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"parttree-001","dir":"Changelog","previous_headings":"","what":"parttree 0.0.1","title":"parttree 0.0.1","text":"Create parttree() generic. (, #3 @zeileis) Support partykit objects (.e. constparty class), turn allows support base plot methods. (#3 @zeileis) ggplot2 moves imports depends now automatically loaded parttree. Add flipaxes argument easy switching case mismatch plot orientation. (#2 @brhkim) Added NEWS.md file track changes package.","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"parttree-0009000","dir":"Changelog","previous_headings":"","what":"parttree 0.0.0.9000","title":"parttree 0.0.0.9000","text":"Initial set functions.","code":""}]
+[{"path":"https://grantmcdermott.com/parttree/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2020 Grant McDermott Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"background","dir":"Articles","previous_headings":"","what":"Background","title":"Abstract art with parttree and friends","text":"One fun application tree-based methods abstracting art images. really striking examples, take look portfolio designer Dimitris Ladopoulos. vignette show implement basic ideas using parttree friends. packages ’ll using. exact details vary depending image hand, essential recipe type art abstraction follows: Convert image matrix (data frame), rows columns correspond, respectively, X Y coordinates individual pixels. words, cell matrix (data frame) represents colour values individual pixel. Split data primary (RGB) colour channels. now three matrices (data frames), cell represents red/green/blue colour channel value individual pixel. Run tree model three RGB datasets. case, trying predict relevant colour channel value function X Y coordinates. Use predicted values plot abstracted art piece! (Okay, step requires bit work, ’re see works practice…)","code":"library(parttree) # This package library(rpart) # For decision trees library(magick) # For reading and manipulating images library(imager) # Another image library, with some additional features op = par(mar = c(0,0,0,0)) # Remove plot margins"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"example-1-peales-portrait-of-rosalba","dir":"Articles","previous_headings":"","what":"Example 1: Peale’s “Portrait of Rosalba”","title":"Abstract art with parttree and friends","text":"first example, mimic one Dimitri Ladopoulos’s aforementioned portrait pieces. Specifically, abstract close-(eyes ) Rembrandt Peale’s portrait daughter, Rosalba. can download digital image original artwork Wikimedia. ’ll download high-res version show , feel free go lower resolution want reduce modeling plotting times.1 However, crop image around Rosalba’s eyes get close-reduce overall complexity exercise.2 cropped image hand, let’s walk 4-step recipe . Step 1 converting image data frame. Step 2 splitting image RGB colour channel. cc column , 1=Red, 2=Green, 3=Blue. Step 3 fitting decision tree (similar model) colour channel data frames. tuning parameters give model matter experimentation. ’m giving low complexity parameter (see variation final predictions) trimming tree maximum depth 30 nodes. next code chunk takes 15 seconds run laptop, much quicker downloaded lower-res image. Step 4 using model (colour) predictions construct abstracted art piece. bit glib earlier, since really involves sub-steps. First, let’s grab predictions trees. ’re going use predictions draw abstracted (downscaled) version image.3 Probably easiest way taking predictions overwriting “value” column original (pre-split) rosalba_df data frame. can coerce data frame back cimg object, comes bunch nice plotting methods. Now ’re ready draw abstracted art piece. ’s also parttree enter fray, since ’ll using highlight partitioned areas downscaled pixels. ’s can using base R plotting functions. can achieve effect ggplot2 prefer use .","code":"# Download the image rosalba = image_read(\"https://upload.wikimedia.org/wikipedia/commons/a/aa/Rembrandt_Peale_-_Portrait_of_Rosalba_Peale_-_Google_Art_Project.jpg\") # Crop around the eyes rosalba = image_crop(rosalba, \"850x400+890+1350\") # rosalba = image_crop(rosalba, \"750x350+890+1350\") # Convert to cimg (better for in-memory manipulation) rosalba = magick2cimg(rosalba) # Display rosalba #> Image. Width: 850 pix Height: 400 pix Depth: 1 Colour channels: 3 plot(rosalba, axes = FALSE) # Coerce to data frame rosalba_df = as.data.frame(rosalba) # Round color values to ease up work for decision tree rosalba_df$value = round(rosalba_df$value, 4) head(rosalba_df) #> x y cc value #> 1 1 1 1 0.3059 #> 2 2 1 1 0.3059 #> 3 3 1 1 0.2627 #> 4 4 1 1 0.2471 #> 5 5 1 1 0.3137 #> 6 6 1 1 0.2941 rosalba_ccs = split(rosalba_df, rosalba_df$cc) # We have a list of three DFs by colour channel. Uncomment if you want to see: # str(rosalba_css) ## Start creating regression tree for each color channel. We'll adjust some ## control parameters to give us the \"right\" amount of resolution in the final ## plots. trees = lapply( rosalba_ccs, # function(d) rpart(value ~ x + y, data=d, control=list(cp=0.00001, maxdepth=20)) function(d) rpart(value ~ x + y, data=d, control=list(cp=0.00002, maxdepth=20)) ) pred = lapply(trees, predict) # get predictions for each tree # The pred object is a list, so we convert it to a vector before overwriting the # value column of the original data frame rosalba_df$value = do.call(\"c\", pred) # Convert back into a cimg object, with the predictions providing pixel values pred_img = as.cimg(rosalba_df) #> Warning in as.cimg.data.frame(rosalba_df): Guessing image dimensions from #> maximum coordinate values # get a list of parttree data frames (one for each tree) pts = lapply(trees, parttree) ## first plot the downscaled image... plot(pred_img, axes = FALSE) ## ... then layer the partitions as a series of rectangles lapply( pts, function(pt) plot( pt, raw = FALSE, add = TRUE, expand = FALSE, fill_alpha = NULL, lwd = 0.1, border = \"grey15\" ) ) #> $`1` #> NULL #> #> $`2` #> NULL #> #> $`3` #> NULL library(ggplot2) ggplot() + annotation_raster(pred_img, ymin=-Inf, ymax=Inf, xmin=-Inf, xmax=Inf) + lapply(trees, function(d) geom_parttree(data = d, lwd = 0.05, col = \"grey15\")) + scale_x_continuous(limits=c(0, max(rosalba_df$x)), expand=c(0,0)) + scale_y_reverse(limits=c(max(rosalba_df$y), 0), expand=c(0,0)) + coord_fixed(ratio = Reduce(x = dim(rosalba)[2:1], f = \"/\") * 2) + theme_void()"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"example-2-parttree-logo","dir":"Articles","previous_headings":"","what":"Example 2: parttree logo","title":"Abstract art with parttree and friends","text":"Now ’ve walked detailed example, let’s quickly go one . ’re get meta: Visualizing decision tree partitions actual tree image. also happens basis parttree logo, seems nice way bookend vignette. main image conversion, modeling, prediction steps. follow recipe saw previous portrait example, won’t repeat explanations. point may tempted plot figure plot(bonzai_pred_img), definitely work. However, ’m going show one additional tweak make partition rectangles look bit nicer: Use mean color channel values instead black. ’s function grabbing information cimg object converted data frame.4 penultimate step generate parttree objects colour channel-based trees. now can plot everything together. , equivalent result prefer ggplot2.","code":"bonzai = load.image(\"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Japanese_Zelkova_bonsai_16%2C_30_April_2012.JPG/480px-Japanese_Zelkova_bonsai_16%2C_30_April_2012.JPG\") plot(bonzai, axes = FALSE) # Coerce to data frame bonzai_df = as.data.frame(bonzai) # Round color values to ease up work for decision trees bonzai_df$value = round(bonzai_df$value, 2) # Split into colour channels bonzai_ccs = split(bonzai_df, bonzai_df$cc) # Fit decision trees on each colour channel DF. Note that I'm deliberating # truncating the max tree depth to reduce the number of partitions. bonzai_trees = lapply( bonzai_ccs, function(d) rpart(value ~ x + y, data=d, control=list(cp=0.00001, maxdepth=10)) ) # Overwrite value column with predictions vector bonzai_df$value = do.call(\"c\", lapply(bonzai_trees, predict)) # Convert back into a cimg object, with the predictions providing pixel values bonzai_pred_img = as.cimg(bonzai_df) #> Warning in as.cimg.data.frame(bonzai_df): Guessing image dimensions from #> maximum coordinate values mean_cols = function(dat) { mcols = tapply(dat$value, dat$cc, FUN = \"mean\") col1 = rgb(mcols[1], mcols[2], mcols[3]) hicol = function(x) mean(x) + 0.4*sd(subset(dat, cc==1)$value) col2 = rgb(hicol(subset(dat, cc==1)$value), hicol(subset(dat, cc==2)$value), hicol(subset(dat, cc==3)$value)) locol = function(x) mean(x) - 0.4*sd(subset(dat, cc==1)$value) col3 = rgb(locol(subset(dat, cc==1)$value), locol(subset(dat, cc==2)$value), locol(subset(dat, cc==3)$value)) return(c(col1, col2, col3)) } bonzai_mean_cols = mean_cols(bonzai_df) bonzai_pts = lapply(bonzai_trees, parttree) plot(bonzai_pred_img, axes = FALSE) Map( function(pt, cols) { plot( pt, raw = FALSE, add = TRUE, expand = FALSE, fill_alpha = 0, lwd = 0.2, border = cols ) }, pt = bonzai_pts, cols = bonzai_mean_cols ) #> $`1` #> NULL #> #> $`2` #> NULL #> #> $`3` #> NULL # library(ggplot2) ggplot() + annotation_raster(bonzai_pred_img, ymin=-Inf, ymax=Inf, xmin=-Inf, xmax=Inf) + Map(function(d, cols) geom_parttree(data = d, lwd = 0.1, col = cols), d = bonzai_trees, cols = bonzai_mean_cols) + scale_x_continuous(limits=c(0, max(bonzai_df$x)), expand=c(0,0)) + scale_y_reverse(limits=c(max(bonzai_df$y), 0), expand=c(0,0)) + coord_fixed() + theme_void()"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-art.html","id":"postscript","dir":"Articles","previous_headings":"","what":"Postscript","title":"Abstract art with parttree and friends","text":"individual trees colour channel make nice stained glass prints…","code":"lapply( seq_along(bonzai_pts), function(i) { plot( bonzai_pts[[i]], raw = FALSE, expand = FALSE, axes = FALSE, legend = FALSE, main = paste0(c(\"R\", \"G\", \"B\")[i]), ## Aside: We're reversing the y-scale since higher values actually ## correspond to points lower on the image, visually. ylim = rev(attr(bonzai_pts[[i]], \"parttree\")[[\"yrange\"]]) ) } ) #> [[1]] #> NULL #> #> [[2]] #> NULL #> #> [[3]] #> NULL # reset the plot margins par(op)"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"motivating-example-classifying-penguin-species","dir":"Articles","previous_headings":"","what":"Motivating example: Classifying penguin species","title":"Introduction to parttree","text":"Start loading parttree package alongside rpart, comes bundled base R installation. basic examples follow, ’ll use well-known Palmer Penguins dataset demonstrate functionality. can load dataset via parent package (), import directly CSV . Dataset hand, let’s say interested predicting penguin species function 1) flipper length 2) bill length. model simple decision tree: Like tree-based frameworks, rpart comes default plot method visualizing resulting node splits. okay, don’t feel provides much intuition model’s prediction scale actual data. words, ’d prefer see : tree partitioned original penguin data? parttree enters fray. package named primary workhorse function parttree(), extracts information needed produce nice plot tree partitions alongside original data. Et voila! Now can clearly see model divided Cartesian space data. Gentoo penguins typically longer flippers Chinstrap Adelie penguins, latter shortest bills. perspective end-user, ptree parttree object interesting . simply data frame contains basic information needed plot (partition coordinates, etc.). can think helpful intermediate object way visualization interest. Speaking visualization, underneath hood plot.parttree calls powerful tinyplot package. latter’s various customization arguments can passed parttree plot make look bit nicer. example:","code":"library(parttree) # This package library(rpart) # For fitting decisions trees # install.packages(\"palmerpenguins\") data(\"penguins\", package = \"palmerpenguins\") head(penguins) #> # A tibble: 6 × 8 #> species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g #> #> 1 Adelie Torgersen 39.1 18.7 181 3750 #> 2 Adelie Torgersen 39.5 17.4 186 3800 #> 3 Adelie Torgersen 40.3 18 195 3250 #> 4 Adelie Torgersen NA NA NA NA #> 5 Adelie Torgersen 36.7 19.3 193 3450 #> 6 Adelie Torgersen 39.3 20.6 190 3650 #> # ℹ 2 more variables: sex , year tree = rpart(species ~ flipper_length_mm + bill_length_mm, data = penguins) tree #> n=342 (2 observations deleted due to missingness) #> #> node), split, n, loss, yval, (yprob) #> * denotes terminal node #> #> 1) root 342 191 Adelie (0.441520468 0.198830409 0.359649123) #> 2) flipper_length_mm< 206.5 213 64 Adelie (0.699530516 0.295774648 0.004694836) #> 4) bill_length_mm< 43.35 150 5 Adelie (0.966666667 0.033333333 0.000000000) * #> 5) bill_length_mm>=43.35 63 5 Chinstrap (0.063492063 0.920634921 0.015873016) * #> 3) flipper_length_mm>=206.5 129 7 Gentoo (0.015503876 0.038759690 0.945736434) * plot(tree, compress = TRUE) text(tree, use.n = TRUE) ptree = parttree(tree) plot(ptree) # See also `attr(ptree, \"parttree\")` ptree #> node species path xmin #> 1 3 Gentoo flipper_length_mm >= 206.5 206.5 #> 2 4 Adelie flipper_length_mm < 206.5 --> bill_length_mm < 43.35 -Inf #> 3 5 Chinstrap flipper_length_mm < 206.5 --> bill_length_mm >= 43.35 -Inf #> xmax ymin ymax #> 1 Inf -Inf Inf #> 2 206.5 -Inf 43.35 #> 3 206.5 43.35 Inf plot(ptree, pch = 16, palette = \"classic\", alpha = 0.75, grid = TRUE)"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"continuous-predictions","dir":"Articles","previous_headings":"Motivating example: Classifying penguin species","what":"Continuous predictions","title":"Introduction to parttree","text":"addition discrete classification problems, parttree also supports regression trees continuous independent variables.","code":"tree_cont = rpart(body_mass_g ~ flipper_length_mm + bill_length_mm, data = penguins) tree_cont |> parttree() |> plot(pch = 16, palette = \"viridis\")"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"supported-model-classes","dir":"Articles","previous_headings":"","what":"Supported model classes","title":"Introduction to parttree","text":"Alongside rpart model objects working thus far, parttree also supports decision trees created partykit package. see latter’s ctree (conditional inference tree) algorithm yields slightly sophisticated partitioning former’s default. parttree also supports variety “frontend” modes call rpart::rpart() underlying engine. includes packages mlr3 tidymodels (parsnip workflows) ecosystems. quick demonstration using parsnip, ’ll also pull different dataset just change things little.","code":"library(partykit) #> Loading required package: grid #> Loading required package: libcoin #> Loading required package: mvtnorm ctree(species ~ flipper_length_mm + bill_length_mm, data = penguins) |> parttree() |> plot(pch = 19, palette = \"classic\", alpha = 0.5) set.seed(123) ## For consistent jitter library(parsnip) library(titanic) ## Just for a different data set titanic_train$Survived = as.factor(titanic_train$Survived) ## Build our tree using parsnip (but with rpart as the model engine) ti_tree = decision_tree() |> set_engine(\"rpart\") |> set_mode(\"classification\") |> fit(Survived ~ Pclass + Age, data = titanic_train) ## Now pass to parttree and plot ti_tree |> parttree() |> plot(pch = 16, jitter = TRUE, palette = \"dark\", alpha = 0.7)"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"ggplot2","dir":"Articles","previous_headings":"","what":"ggplot2","title":"Introduction to parttree","text":"default plot.parttree method produces base graphics plot. also support ggplot2 via dedicated geom_parttree() function. demonstrate initial classification tree earlier. Compared “native” plot.parttree method, note ggplot2 workflow requires tweaks: need need plot original dataset separate layer (.e., geom_point()). geom_parttree() accepts tree object , result parttree().1 Continuous regression trees can also drawn geom_parttree. However, recommend adjusting plot fill aesthetic since model likely partition data intervals don’t match exactly raw data. easiest way setting colour fill aesthetic together part scale_colour_* call.","code":"library(ggplot2) theme_set(theme_linedraw()) ## re-using the tree model object from above... ggplot(data = penguins, aes(x = flipper_length_mm, y = bill_length_mm)) + geom_point(aes(col = species)) + geom_parttree(data = tree, aes(fill=species), alpha = 0.1) ## re-using the tree_cont model object from above... ggplot(data = penguins, aes(x = flipper_length_mm, y = bill_length_mm)) + geom_parttree(data = tree_cont, aes(fill=body_mass_g), alpha = 0.3) + geom_point(aes(col = body_mass_g)) + scale_colour_viridis_c(aesthetics = c('colour', 'fill')) # NB: Set colour + fill together"},{"path":"https://grantmcdermott.com/parttree/articles/parttree-intro.html","id":"gotcha-ggplot-orientation","dir":"Articles","previous_headings":"ggplot2","what":"Gotcha: (gg)plot orientation","title":"Introduction to parttree","text":"already said, geom_parttree() calls companion parttree() function internally, coerces rpart tree object data frame easily understood ggplot2. example, consider initial “ptree” object earlier. , resulting data frame designed amenable ggplot2 geom layer, columns like xmin, xmax, etc. specifying aesthetics ggplot2 recognizes. (Fun fact: geom_parttree() really just thin wrapper around geom_rect().) goal parttree abstract away kinds details user, can just specify geom_parttree()—valid tree object data input—done . However, generally works well, can sometimes lead unexpected behaviour terms plot orientation. ’s ’s hard guess ahead time user specify x y variables (.e. axes) ggplot2 layers.2 see mean, let’s redo penguin plot earlier, time switch axes main ggplot() call. case , kind orientation mismatch normally (hopefully) pretty easy recognize. fix, can use flip = TRUE argument flip orientation geom_parttree layer.","code":"# ptree = parttree(tree) ptree #> node species path xmin #> 1 3 Gentoo flipper_length_mm >= 206.5 206.5 #> 2 4 Adelie flipper_length_mm < 206.5 --> bill_length_mm < 43.35 -Inf #> 3 5 Chinstrap flipper_length_mm < 206.5 --> bill_length_mm >= 43.35 -Inf #> xmax ymin ymax #> 1 Inf -Inf Inf #> 2 206.5 -Inf 43.35 #> 3 206.5 43.35 Inf ## First, redo our first plot but this time switch the x and y variables p3 = ggplot( data = penguins, aes(x = bill_length_mm, y = flipper_length_mm) ## Switched! ) + geom_point(aes(col = species)) ## Add on our tree (and some preemptive titling..) p3 + geom_parttree(data = tree, aes(fill = species), alpha = 0.1) + labs( title = \"Oops!\", subtitle = \"Looks like a mismatch between our x and y axes...\" ) p3 + geom_parttree( data = tree, aes(fill = species), alpha = 0.1, flip = TRUE ## Flip the orientation ) + labs(title = \"That's better\")"},{"path":"https://grantmcdermott.com/parttree/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Grant McDermott. Author, maintainer. Achim Zeileis. Contributor. Brian Heseung Kim. Contributor. Julia Silge. Contributor.","code":""},{"path":"https://grantmcdermott.com/parttree/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"McDermott G (2025). parttree: Visualise simple decision tree partitions. R package version 0.0.1.9005, http://grantmcdermott.com/parttree, https://github.com/grantmcdermott/parttree.","code":"@Manual{, title = {parttree: Visualise simple decision tree partitions}, author = {Grant McDermott}, year = {2025}, note = {R package version 0.0.1.9005, http://grantmcdermott.com/parttree}, url = {https://github.com/grantmcdermott/parttree}, }"},{"path":"https://grantmcdermott.com/parttree/index.html","id":"parttree-","dir":"","previous_headings":"","what":"Visualise simple decision tree partitions","title":"Visualise simple decision tree partitions","text":"Visualize simple 2-D decision tree partitions R. parttree package provides visualization methods base R graphics (via tinyplot) ggplot2.","code":""},{"path":"https://grantmcdermott.com/parttree/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Visualise simple decision tree partitions","text":"package CRAN yet, can installed r-universe:","code":"install.packages(\"parttree\", repos = \"https://grantmcdermott.r-universe.dev\")"},{"path":"https://grantmcdermott.com/parttree/index.html","id":"quickstart","dir":"","previous_headings":"","what":"Quickstart","title":"Visualise simple decision tree partitions","text":"parttree homepage includes introductory vignette detailed documentation. ’s quickstart example using “kyphosis” dataset comes bundled rpart package. case, interested predicting kyphosis recovery spinal surgery, function 1) number topmost vertebra operated, 2) patient age. key function parttree(), comes plotting method. Customize plots passing additional arguments:","code":"library(rpart) # For the dataset and fitting decisions trees library(parttree) # This package fit = rpart(Kyphosis ~ Start + Age, data = kyphosis) # Grab the partitions and plot fit_pt = parttree(fit) plot(fit_pt) 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 )"},{"path":"https://grantmcdermott.com/parttree/index.html","id":"ggplot2","dir":"","previous_headings":"Quickstart","what":"ggplot2","title":"Visualise simple decision tree partitions","text":"ggplot2 users, offer equivalent workflow via geom_partree() visualization layer.","code":"library(ggplot2) ## Should be loaded separately ggplot(kyphosis, aes(x = Start, y = Age)) + geom_parttree(data = fit, alpha = 0.1, aes(fill = Kyphosis)) + # <-- key layer geom_point(aes(col = Kyphosis)) + labs( x = \"No. of topmost vertebra operated on\", y = \"Patient age (months)\", caption = \"Note: Points denote observations. Shading denotes model predictions.\" ) + theme_minimal()"},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":null,"dir":"Reference","previous_headings":"","what":"Visualize tree partitions with ggplot2 — geom_parttree","title":"Visualize tree partitions with ggplot2 — geom_parttree","text":"geom_parttree() simple wrapper around parttree() takes tree model object converts amenable data frame ggplot2 knows plot. Please note ggplot2 hard dependency parttree must thus installed separately user's system calling geom_parttree.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Visualize tree partitions with ggplot2 — geom_parttree","text":"","code":"geom_parttree( mapping = NULL, data = NULL, stat = \"identity\", position = \"identity\", linejoin = \"mitre\", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, flip = FALSE, ... )"},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Visualize tree partitions with ggplot2 — geom_parttree","text":"mapping Set aesthetic mappings created aes(). specified inherit.aes = TRUE (default), combined default mapping top level plot. must supply mapping plot mapping. data rpart::rpart.object object compatible type (e.g. decision tree constructed via partykit, tidymodels, mlr3 front-ends). stat statistical transformation use data layer. using geom_*() function construct layer, stat argument can used override default coupling geoms stats. stat argument accepts following: Stat ggproto subclass, example StatCount. string naming stat. give stat string, strip function name stat_ prefix. example, use stat_count(), give stat \"count\". information ways specify stat, see layer stat documentation. position position adjustment use data layer. can used various ways, including prevent overplotting improving display. position argument accepts following: result calling position function, position_jitter(). method allows passing extra arguments position. string naming position adjustment. give position string, strip function name position_ prefix. example, use position_jitter(), give position \"jitter\". information ways specify position, see layer position documentation. linejoin Line join style (round, mitre, bevel). na.rm FALSE, default, missing values removed warning. TRUE, missing values silently removed. show.legend logical. layer included legends? NA, default, includes aesthetics mapped. FALSE never includes, TRUE always includes. can also named logical vector finely select aesthetics display. inherit.aes FALSE, overrides default aesthetics, rather combining . useful helper functions define data aesthetics inherit behaviour default plot specification, e.g. borders(). flip Logical. default, \"x\" \"y\" axes variables plotting determined first split tree. can cause plot orientation mismatches depending users specify layers plot. Setting TRUE flip \"x\" \"y\" variables geom_parttree layer. ... arguments passed layer()'s params argument. arguments broadly fall one 4 categories . Notably, arguments position argument, aesthetics required can passed .... Unknown arguments part 4 categories ignored. Static aesthetics mapped scale, fixed value apply layer whole. example, colour = \"red\" linewidth = 3. geom's documentation Aesthetics section lists available options. 'required' aesthetics passed params. Please note passing unmapped aesthetics vectors technically possible, order required length guaranteed parallel input data. constructing layer using stat_*() function, ... argument can used pass parameters geom part layer. example stat_density(geom = \"area\", outline.type = \"\"). geom's documentation lists parameters can accept. Inversely, constructing layer using geom_*() function, ... argument can used pass parameters stat part layer. example geom_area(stat = \"density\", adjust = 0.5). stat's documentation lists parameters can accept. key_glyph argument layer() may also passed .... can one functions described key glyphs, change display layer legend.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Visualize tree partitions with ggplot2 — geom_parttree","text":"way ggplot2 validates inputs assembles plot layers, note data input geom_parttree() (.e. decision tree object) must assigned layer ; initialising ggplot2::ggplot() call. See Examples.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"aesthetics","dir":"Reference","previous_headings":"","what":"Aesthetics","title":"Visualize tree partitions with ggplot2 — geom_parttree","text":"geom_parttree() aims \"work----box\" minimal input user's side, apart specifying data object. includes taking care data transformation way , generally, produces optimal corner coordinates partition (.e. xmin, xmax, ymin, ymax). However, also understands following aesthetics users may choose specify manually: fill (particularly encouraged, since provide visual cue regarding prediction partition region) colour alpha linetype size","code":""},{"path":[]},{"path":"https://grantmcdermott.com/parttree/reference/geom_parttree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Visualize tree partitions with ggplot2 — geom_parttree","text":"","code":"# install.packages(\"ggplot2\") library(ggplot2) # ggplot2 must be installed/loaded separately library(parttree) # this package library(rpart) # decision trees ### Simple decision tree (max of two predictor variables) iris_tree = rpart(Species ~ Petal.Length + Petal.Width, data=iris) ## 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) p + geom_parttree(data = iris_tree) ## 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) p + geom_parttree(data = iris_tree, aes(fill = Species), col = NA, alpha = 0.1) ### Example with plot orientation mismatch p2 = ggplot(iris, aes(x=Petal.Width, y=Petal.Length)) + geom_point(aes(col=Species)) ## Oops p2 + geom_parttree(data = iris_tree, aes(fill=Species), alpha = 0.1) ## Fix with 'flip = TRUE' ### 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\") |> fit(Species ~ Petal.Length + Petal.Width, data=iris) p + geom_parttree(data = iris_tree_parsnip, aes(fill=Species), alpha = 0.1) ### 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.: iris_tree_cont = rpart(Petal.Length ~ Sepal.Length + Petal.Width, data=iris) p3 = ggplot(data = iris, aes(x = Petal.Width, y = Sepal.Length)) + geom_parttree( data = iris_tree_cont, aes(fill = Petal.Length), alpha=0.5 ) + geom_point(aes(col = Petal.Length)) + theme_minimal() ## Legend scales don't quite match here: p3 ## Better to scale fill to the original data p3 + scale_fill_continuous(limits = range(iris$Petal.Length))"},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert a decision tree into a data frame of partition coordinates — parttree","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"Extracts terminal leaf nodes decision tree contains two numeric predictor variables. leaf nodes converted data frame, row represents partition (leaf terminal node) can easily plotted 2-D coordinate space.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"","code":"parttree(tree, keep_as_dt = FALSE, flip = FALSE)"},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"tree rpart.object alike. includes compatible classes mlr3 tidymodels frontends, constparty class inheriting party. keep_as_dt Logical. function relies data.table internal data manipulation. coerce final return object regular data frame (default behavior) unless user specifies TRUE. flip Logical. flip \"x\" \"y\" variables return data frame? default behaviour first split variable tree take \"y\" slot, second split variable take \"x\" slot. Setting TRUE switches around.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"data frame comprising seven columns: leaf node, path, set rectangle limits (.e., xmin, xmax, ymin, ymax), final column corresponding predicted value leaf.","code":""},{"path":[]},{"path":"https://grantmcdermott.com/parttree/reference/parttree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Convert a decision tree into a data frame of partition coordinates — parttree","text":"","code":"library(\"parttree\") ## rpart trees library(\"rpart\") rp = rpart(Kyphosis ~ Start + Age, data = kyphosis) # A parttree object is just a data frame with additional attributes (rp_pt = parttree(rp)) #> node Kyphosis path xmin #> 1 3 present Start < 8.5 -Inf #> 2 4 absent Start >= 8.5 --> Start >= 14.5 14.5 #> 3 10 absent Start >= 8.5 --> Start < 14.5 --> Age < 55 8.5 #> 4 22 absent Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 5 23 present Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age < 111 8.5 #> xmax ymin ymax #> 1 8.5 -Inf Inf #> 2 Inf -Inf Inf #> 3 14.5 -Inf 55 #> 4 14.5 111 Inf #> 5 14.5 55 111 attr(rp_pt, \"parttree\") #> $xvar #> [1] \"Start\" #> #> $yvar #> [1] \"Age\" #> #> $xrange #> [1] 1 18 #> #> $yrange #> [1] 1 206 #> #> $response #> [1] \"Kyphosis\" #> #> $call #> rpart(formula = Kyphosis ~ Start + Age, data = kyphosis) #> #> $na.action #> NULL #> #> $raw_data #> NULL #> # simple plot plot(rp_pt) # removing the (recursive) partition borders helps to emphasise overall fit 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 main = \"Tree predictions: Kyphosis recurrence\" # custom title ) ## conditional inference trees from partyit library(\"partykit\") #> Loading required package: grid #> Loading required package: libcoin #> Loading required package: mvtnorm ct = ctree(Species ~ Petal.Length + Petal.Width, data = iris) ct_pt = parttree(ct) plot(ct_pt, pch = 19, palette = \"okabe\", main = \"ctree predictions: iris species\") #> Error in eval(raw_data): object 'ct' not found ## rpart via partykit rp2 = as.party(rp) parttree(rp2) #> node Kyphosis path xmin #> 3 3 absent Start < 8.5 --> Start < 14.5 14.5 #> 5 5 absent Start < 8.5 --> Start >= 14.5 --> Age < 55 8.5 #> 7 7 absent Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age < 111 8.5 #> 8 8 present Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 9 9 present Start >= 8.5 -Inf #> xmax ymin ymax #> 3 Inf -Inf Inf #> 5 14.5 -Inf 55 #> 7 14.5 111 Inf #> 8 14.5 55 111 #> 9 8.5 -Inf Inf ## various front-end frameworks are also supported, e.g. # tidymodels library(parsnip) decision_tree() |> set_engine(\"rpart\") |> set_mode(\"classification\") |> fit(Species ~ Petal.Length + Petal.Width, data=iris) |> parttree() |> plot(main = \"This time brought to you via parsnip...\") # mlr3 (NB: use `keep_model = TRUE` for mlr3 learners) library(mlr3) task_iris = TaskClassif$new(\"iris\", iris, target = \"Species\") task_iris$formula(rhs = \"Petal.Length + Petal.Width\") #> Species ~ `Petal.Length + Petal.Width` #> NULL fit_iris = lrn(\"classif.rpart\", keep_model = TRUE) # NB! fit_iris$train(task_iris) plot(parttree(fit_iris), main = \"... and now mlr3\")"},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot decision tree partitions — plot.parttree","title":"Plot decision tree partitions — plot.parttree","text":"Provides plot method parttree objects.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot decision tree partitions — plot.parttree","text":"","code":"# S3 method for class 'parttree' plot( x, raw = TRUE, border = \"black\", fill_alpha = 0.3, expand = TRUE, jitter = FALSE, add = FALSE, ... )"},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot decision tree partitions — plot.parttree","text":"x parttree data frame. raw Logical. raw (original) data points plotted ? Default TRUE. border Colour partition borders (edges). Default \"black\". remove borders altogether, specify NA. fill_alpha Numeric range [0,1]. Alpha transparency filled partition rectangles. Default 0.3. expand Logical. partition limits expanded meet edge plot axes? Default TRUE. FALSE, partition limits extend range raw data. jitter Logical. raw points jittered? Default FALSE. evaluated raw = TRUE. add Logical. Add existing plot? Default FALSE. ... Additional arguments passed tinyplot.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot decision tree partitions — plot.parttree","text":"return value, called side effect producing plot. return value; called side effect producing plot.","code":""},{"path":"https://grantmcdermott.com/parttree/reference/plot.parttree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot decision tree partitions — plot.parttree","text":"","code":"library(\"parttree\") ## rpart trees library(\"rpart\") rp = rpart(Kyphosis ~ Start + Age, data = kyphosis) # A parttree object is just a data frame with additional attributes (rp_pt = parttree(rp)) #> node Kyphosis path xmin #> 1 3 present Start < 8.5 -Inf #> 2 4 absent Start >= 8.5 --> Start >= 14.5 14.5 #> 3 10 absent Start >= 8.5 --> Start < 14.5 --> Age < 55 8.5 #> 4 22 absent Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 5 23 present Start >= 8.5 --> Start < 14.5 --> Age >= 55 --> Age < 111 8.5 #> xmax ymin ymax #> 1 8.5 -Inf Inf #> 2 Inf -Inf Inf #> 3 14.5 -Inf 55 #> 4 14.5 111 Inf #> 5 14.5 55 111 attr(rp_pt, \"parttree\") #> $xvar #> [1] \"Start\" #> #> $yvar #> [1] \"Age\" #> #> $xrange #> [1] 1 18 #> #> $yrange #> [1] 1 206 #> #> $response #> [1] \"Kyphosis\" #> #> $call #> rpart(formula = Kyphosis ~ Start + Age, data = kyphosis) #> #> $na.action #> NULL #> #> $raw_data #> NULL #> # simple plot plot(rp_pt) # removing the (recursive) partition borders helps to emphasise overall fit 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 main = \"Tree predictions: Kyphosis recurrence\" # custom title ) ## conditional inference trees from partyit library(\"partykit\") ct = ctree(Species ~ Petal.Length + Petal.Width, data = iris) ct_pt = parttree(ct) plot(ct_pt, pch = 19, palette = \"okabe\", main = \"ctree predictions: iris species\") #> Error in eval(raw_data): object 'ct' not found ## rpart via partykit rp2 = as.party(rp) parttree(rp2) #> node Kyphosis path xmin #> 3 3 absent Start < 8.5 --> Start < 14.5 14.5 #> 5 5 absent Start < 8.5 --> Start >= 14.5 --> Age < 55 8.5 #> 7 7 absent Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age < 111 8.5 #> 8 8 present Start < 8.5 --> Start >= 14.5 --> Age >= 55 --> Age >= 111 8.5 #> 9 9 present Start >= 8.5 -Inf #> xmax ymin ymax #> 3 Inf -Inf Inf #> 5 14.5 -Inf 55 #> 7 14.5 111 Inf #> 8 14.5 55 111 #> 9 8.5 -Inf Inf ## various front-end frameworks are also supported, e.g. # tidymodels library(parsnip) decision_tree() |> set_engine(\"rpart\") |> set_mode(\"classification\") |> fit(Species ~ Petal.Length + Petal.Width, data=iris) |> parttree() |> plot(main = \"This time brought to you via parsnip...\") # mlr3 (NB: use `keep_model = TRUE` for mlr3 learners) library(mlr3) task_iris = TaskClassif$new(\"iris\", iris, target = \"Species\") task_iris$formula(rhs = \"Petal.Length + Petal.Width\") #> Species ~ `Petal.Length + Petal.Width` #> NULL fit_iris = lrn(\"classif.rpart\", keep_model = TRUE) # NB! fit_iris$train(task_iris) plot(parttree(fit_iris), main = \"... and now mlr3\")"},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"parttree-0019005","dir":"Changelog","previous_headings":"","what":"parttree 0.0.1.9005","title":"parttree 0.0.1.9005","text":"released 0.1.0","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"breaking-changes-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Breaking changes","title":"parttree 0.0.1.9005","text":"Move ggplot2 Suggests, following addition native (base R) plot.parttree method. geom_parttree() function now checks whether ggplot2 available user’s system executing code. (#18) flipaxes argument renamed flip, e.g. parttree(..., flip = TRUE). (#18)","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"improvements-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Improvements","title":"parttree 0.0.1.9005","text":"Parttree objects now class dedicated plot.parttree method, powered tinyplot. (#18) Major speed-extracting parttree nodes coordinates complicated trees. (#15) Add method tidymodels workflows objects fitted \"rpart\" engine. (#7 @juliasilge).","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"bug-fixes-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Bug fixes","title":"parttree 0.0.1.9005","text":"Support negative values. (#6 @pjgeens) Better handling single-level factors flip(axes). (#5)","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"internals-0-0-1-9005","dir":"Changelog","previous_headings":"","what":"Internals","title":"parttree 0.0.1.9005","text":"Several dependency adjustments, e.g. tinyplot Imports ggplot2 Suggests. (#18) Added SVG snapshots image-based tests. (#18) Bump ggplot2 version dependency match deprecated functions 3.4.0. Switched “main” primary GitHub branch development. Added two dedicated vignettes.","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"parttree-001","dir":"Changelog","previous_headings":"","what":"parttree 0.0.1","title":"parttree 0.0.1","text":"Create parttree() generic. (, #3 @zeileis) Support partykit objects (.e. constparty class), turn allows support base plot methods. (#3 @zeileis) ggplot2 moves imports depends now automatically loaded parttree. Add flipaxes argument easy switching case mismatch plot orientation. (#2 @brhkim) Added NEWS.md file track changes package.","code":""},{"path":"https://grantmcdermott.com/parttree/news/index.html","id":"parttree-0009000","dir":"Changelog","previous_headings":"","what":"parttree 0.0.0.9000","title":"parttree 0.0.0.9000","text":"Initial set functions.","code":""}]