Skip to content

4 geom_node_label

Martin edited this page Jun 28, 2019 · 2 revisions

Node Labels

geom_node_label() is a modified version of ggplot2’s geom_label() which allows for multi-line labels. However the basic functionality of geom_label() is still present. This means that if we are content with uniform aesthetics for the whole label, we can simply use geom_node_label() as we would geom_label() with the only difference, that x and y are already mapped per default to the nodes coordinates.

If we want to have to specify even less mappings, we can use geom_node_splitvar() and geom_node_info(). These are wrappers of geom_node_label() with the respective defaults to plot the splitvar in the inner nodes or the info in the terminal nodes.

Multi-Line Labels

geom_node_label() allows us to create multiline labels and specify individual graphical parameters for each line. To do this, we must not map anything to label in the aes() passed to mapping, but instead pass a 'list' of aes() to the argument line_list. The order of the 'list' is the same as the order in which the lines will be printed. Additionally we have to pass a 'list' to line_gpar. This list must be the same length as line_list and contain separately named 'lists' of graphical parameters. If we don’t want to change anything for a specific line, the respective ’list' hast to be an empty 'list'.

Mapping with the mapping argument of geom_node_label() still works and affects all lines and the border together. The line specific graphical arguments in line_gpar can be used to overwrite these mappings.
Additionally to the usual aethetic parameters we would use for ggplot’s geom_label() we can pass parse and alignment through line_gpar. Parse is equivalent to the behaviour of geom_label() and alignment enables us to position the text at the left or right label border.

All other mappings in line_list will be ignored. It is not possible to map other line specific aesthetics to variables. It is only possible to map the aesthetics of the complete label to variables and overwrite specific lines with fixed values in line_gpar. (In essence replicating the condition of mapping only one line to a variable, but we won’t be able to do this for multiple lines with different mappings).

This may seem very convoluted, but keep in mind, that we only have to go through this process if we want to address the graphical parameters of specific lines.

Example

To create a tree consisting of inner nodes labeled by their split variable and terminal nodes labeled by their coefficients we can use the code found below.

First we need to extract the coefficients with the help of the add_vars argument of ggparty(). This step is necessary so that we can later access them by the names given to them in the 'list' supplied to add_vars.

Since we want to plot different elements in the inner and terminal nodes, we need to add geom_node_label() twice. The first call is for the inner nodes. With the aes() passed to mapping we map the color of the labels to the splitvar of the node.

For this tree we want to display the split variable in the first line, then the p-value in scientific notation in the second line, the third line is just a spacer therefore empty and the fourth and last line is supposed to show the ID of the node. We specify the aesthetics we want to override in line_gpar. Using the third line as a spacer and setting alignment to “left” we can position the id of the node at the bottom left corner of the labels.
Correspondingly we can plot the labels for the terminal nodes.

data("TeachingRatings", package = "AER")
tr <- subset(TeachingRatings, credits == "more")

tr_tree <- lmtree(eval ~ beauty | minority + age + gender + division + native +
                    tenure, data = tr, weights = students, caseweights = FALSE)

ggparty(tr_tree,
        terminal_space = 0,
        add_vars = list(intercept = "$node$info$coefficients[1]",
                        beta = "$node$info$coefficients[2]")) +
  geom_edge(size = 1.5) +
  geom_edge_label(colour = "grey", size = 4) +
  # first label inner nodes
  geom_node_label(# map color of complete label to splitvar
                  mapping = aes(col = splitvar),
                  # map content to label for each line
                  line_list = list(aes(label = splitvar),
                                   aes(label = paste("p =",
                                                     formatC(p.value,
                                                             format = "e",
                                                             digits = 2))),
                                   aes(label = ""),
                                   aes(label = id)
                  ),
                  # set graphical parameters for each line in same order
                  line_gpar = list(list(size = 12),
                                   list(size = 8),
                                   list(size = 6),
                                   list(size = 7,
                                        col = "black",
                                        fontface = "bold",
                                        alignment = "left")
                  ),
                  # only inner nodes
                  ids = "inner") +
  # next label terminal nodes
  geom_node_label(# map content to label for each line
                  line_list = list(
                    aes(label = paste("beta[0] == ", round(intercept, 2))),
                    aes(label = paste("beta[1] == ",round(beta, 2))),
                    aes(label = ""),
                    aes(label = id)
                  ),
                  # set graphical parameters for each line in same order
                  line_gpar = list(list(size = 12, parse = T),
                                   list(size = 12, parse = T),
                                   list(size = 6),
                                   list(size = 7,
                                        col = "black",
                                        fontface = "bold",
                                        alignment = "left")),
                  ids = "terminal",
                  # nudge labels towards bottom so that edge labels have enough space
                  # alternatively use shift argument of edge_label
                  nudge_y = -.05) +
  # don't show legend for splitvar mapping to color since self-explanatory
  theme(legend.position = "none") +
  # html_documents seem to cut off a bit too much at the edges so set limits manually
  coord_cartesian(xlim = c(0, 1), ylim = c(-0.1, 1.1))

Clone this wiki locally