rparty

terminal_panel function not applied in plotting an glmertree object


I fitted a glmtertree model and like to apply a modified node_barplot function my_node_barplot for plotting. However, it seems that function my_node_barpolot is not passed to the plot.constparty function, resulting in using the node_barplot function shipped with package partykit.

Reproducible example from package glmertree vignette:

library("glmertree")
data("MHserviceDemo", package = "glmertree")
MHserviceDemo$outcome_bin <- factor(MHserviceDemo$outcome > 0)
MH_gtree <- glmertree(outcome_bin ~ 1 | cluster_id | age + gender +
                      emotional + autism + impact + conduct,
                      data = MHserviceDemo, family = "binomial")
plot(MH_gtree, which = "tree")
plot(MH_gtree, which = "tree", terminal_panel = my_node_barplot)

shows the same plot. my_panel_barplot is a slightly modified version of panel_barplot from GitHub, I changed the lines building the mainlab variable to print more information::

## ... skipped
function(id, nobs) sprintf("Node %s (n = %s)", id, nobs)
## rest skipped ...

to

## ... skipped
function(id, nobs, resp) {
      frq <- table(resp)
      perc <- round(frq[1]/sum(frq)*100, 1)
      sprintf("Node %s (n = %s)\n: %s%% (%s/%s)",
               id, nobs, perc, frq[1], sum(frq))
} else {
   function(id, nobs, resp) sprintf("n = %s", nobs)
   }
}
if (is.function(mainlab)) {
      mainlab <- mainlab(names(obj)[nid], nobs[nid], y)
} 
## skipped ...

The function has many lines, but when helpful I can post or share it.


Solution

  • You are right the the terminal_panel argument is ignored in this specific setup. The reason is that the plot() method for glmertree objects mainly focuses on displaying trees that have a real regressor (e.g., a treatment variable) as part of the GLMM specification. In contrast, the case with an intercept-only regressor (as in your example) is passed on to glmtree which the uses coercion to constparty and applies defaults for that. This solution is very convenient if you accept the default but to pass on arguments we would have to replicate some of the code from partykit in glmertree. I will discuss with Marjolein, the lead author, whether this is worth the effort.

    The workaround for your specific case is to do the coercion to constparty yourself. Subsequently you can use all the standard strategies for extending the plots of that, e.g.,

    MH_ctree <- as.constparty(MH_gtree)
    plot(MH_ctree, terminal_panel = my_node_barplot)
    

    constparty with custom my_node_barplot

    Note that I removed the line break within the mainlab which still works well for this particular plot. For plots with more terminal nodes you are likely to need the line break. Then you need to increase the number of lines for the mainlab as well.

    Finally, rather than going through the internals of node_barplot you can also compose the mainlab outside of the tree and then insert it via the mainlab argument. See this post for a worked example:

    partykit: Displaying terminal node percentile values above terminal node boxplots