I am using the ctree
function from partykit
.
library(rpart)
library(partykit)
fit <- ctree(Kyphosis ~ Age + Number + Start, data=kyphosis)
plot(fit, terminal_panel=node_barplot)
I want to add an additional horizonal line to each barplot, indicating the average reponse across the dataset, i.e. at 0.79 here.
prop.table(table(kyphosis$Kyphosis))
absent present
0.7901235 0.2098765
Approach: I started to modify the node_barplot
function that is passed to the terminal_panel
argument. But the source code is very long and comes with almost no comments. So I tried to go step by step, stripping down the function to its first two lines of code (plus an extra print command). However, if I run it, the object y
is NULL
and an error is thrown.
node_barplot2 <- function(obj, ...)
{
y <- obj$fitted[["(response)"]] # first lime from node_barplot source
print(y)
stopifnot(is.factor(y) || isTRUE(all.equal(round(y), y)) || is.data.frame(y))
}
plot(fit, terminal_panel=node_barplot2)
> Error in round(y) : Non-numeric argument in mathematical function
As its the original code, I do not quite see where I go wrong here and how I could draw the horizontal line. Any ideas?
The partykit
distinguishes "panel" functions and "panel-generating" functions:
The former just expect the
node
of a tree as their sole argument and then draw this node (usinggrid
graphics).The latter expect a full tree as their first argument plus further arguments for customization. They return a "panel" function (with only argument
node
) where certain informations like the x and y ranges are stored in the function environment.
To signal that a function is a panel-generating function, it has to have class "grapcon_generator"
. Hence
class(node_barplot)
## [1] "grapcon_generator"
To add certain graphical elements to the function, I would recommend copying the whole node_barplot
source code (including the class assignment at the end) and then add the elements you need, e.g., a horizontal reference line you can draw with grid.lines()
.
Just for completeness: As Achim explained, the class attribute was not correct to indicate that the function has to be passed the whole tree, not just a node. Setting it to class(node_barplot2) <- "grapcon_generator"
does the trick.
I slightly tweaked the node_barplot
code and added two new arguments to the function: hline
and h.gp
. The first one specifies where the horizontal line is drawn (a value between 0 and 1). The line is the same across all terminal panels. The second one takes a gpar
object used to style the drawn line. The function is named node_barplot2
, you can find the gist here. The code that draws the line is at the end.
Example
library(devtools)
source_gist("0313362f0c84b21625bd")
plot(fit, terminal_panel = node_barplot2,
tp_args= list(hline = .8,
h.gp = gpar(lwd=4, col="blue")))
来源:https://stackoverflow.com/questions/33784109/add-horizontal-line-to-terminal-barplots-in-party-partykit-trees